006-Prevent-reinstallation-of-an-already-in-use-group-ke.patch 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. From: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
  2. Date: Wed, 12 Jul 2017 16:03:24 +0200
  3. Subject: [PATCH] Prevent reinstallation of an already in-use group key
  4. Track the current GTK and IGTK that is in use and when receiving a
  5. (possibly retransmitted) Group Message 1 or WNM-Sleep Mode Response, do
  6. not install the given key if it is already in use. This prevents an
  7. attacker from trying to trick the client into resetting or lowering the
  8. sequence counter associated to the group key.
  9. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
  10. ---
  11. --- a/src/common/wpa_common.h
  12. +++ b/src/common/wpa_common.h
  13. @@ -207,6 +207,17 @@ struct wpa_ptk {
  14. size_t tk_len;
  15. };
  16. +struct wpa_gtk {
  17. + u8 gtk[WPA_GTK_MAX_LEN];
  18. + size_t gtk_len;
  19. +};
  20. +
  21. +#ifdef CONFIG_IEEE80211W
  22. +struct wpa_igtk {
  23. + u8 igtk[WPA_IGTK_MAX_LEN];
  24. + size_t igtk_len;
  25. +};
  26. +#endif /* CONFIG_IEEE80211W */
  27. /* WPA IE version 1
  28. * 00-50-f2:1 (OUI:OUI type)
  29. --- a/src/rsn_supp/wpa.c
  30. +++ b/src/rsn_supp/wpa.c
  31. @@ -785,6 +785,15 @@ static int wpa_supplicant_install_gtk(st
  32. const u8 *_gtk = gd->gtk;
  33. u8 gtk_buf[32];
  34. + /* Detect possible key reinstallation */
  35. + if (sm->gtk.gtk_len == (size_t) gd->gtk_len &&
  36. + os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) {
  37. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  38. + "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
  39. + gd->keyidx, gd->tx, gd->gtk_len);
  40. + return 0;
  41. + }
  42. +
  43. wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
  44. wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  45. "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
  46. @@ -819,6 +828,9 @@ static int wpa_supplicant_install_gtk(st
  47. }
  48. os_memset(gtk_buf, 0, sizeof(gtk_buf));
  49. + sm->gtk.gtk_len = gd->gtk_len;
  50. + os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
  51. +
  52. return 0;
  53. }
  54. @@ -925,6 +937,48 @@ static int wpa_supplicant_pairwise_gtk(s
  55. }
  56. +#ifdef CONFIG_IEEE80211W
  57. +static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
  58. + const struct wpa_igtk_kde *igtk)
  59. +{
  60. + size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
  61. + u16 keyidx = WPA_GET_LE16(igtk->keyid);
  62. +
  63. + /* Detect possible key reinstallation */
  64. + if (sm->igtk.igtk_len == len &&
  65. + os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) {
  66. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  67. + "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
  68. + keyidx);
  69. + return 0;
  70. + }
  71. +
  72. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  73. + "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x",
  74. + keyidx, MAC2STR(igtk->pn));
  75. + wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
  76. + if (keyidx > 4095) {
  77. + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  78. + "WPA: Invalid IGTK KeyID %d", keyidx);
  79. + return -1;
  80. + }
  81. + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
  82. + broadcast_ether_addr,
  83. + keyidx, 0, igtk->pn, sizeof(igtk->pn),
  84. + igtk->igtk, len) < 0) {
  85. + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  86. + "WPA: Failed to configure IGTK to the driver");
  87. + return -1;
  88. + }
  89. +
  90. + sm->igtk.igtk_len = len;
  91. + os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
  92. +
  93. + return 0;
  94. +}
  95. +#endif /* CONFIG_IEEE80211W */
  96. +
  97. +
  98. static int ieee80211w_set_keys(struct wpa_sm *sm,
  99. struct wpa_eapol_ie_parse *ie)
  100. {
  101. @@ -935,30 +989,14 @@ static int ieee80211w_set_keys(struct wp
  102. if (ie->igtk) {
  103. size_t len;
  104. const struct wpa_igtk_kde *igtk;
  105. - u16 keyidx;
  106. +
  107. len = wpa_cipher_key_len(sm->mgmt_group_cipher);
  108. if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
  109. return -1;
  110. +
  111. igtk = (const struct wpa_igtk_kde *) ie->igtk;
  112. - keyidx = WPA_GET_LE16(igtk->keyid);
  113. - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
  114. - "pn %02x%02x%02x%02x%02x%02x",
  115. - keyidx, MAC2STR(igtk->pn));
  116. - wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
  117. - igtk->igtk, len);
  118. - if (keyidx > 4095) {
  119. - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  120. - "WPA: Invalid IGTK KeyID %d", keyidx);
  121. + if (wpa_supplicant_install_igtk(sm, igtk) < 0)
  122. return -1;
  123. - }
  124. - if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
  125. - broadcast_ether_addr,
  126. - keyidx, 0, igtk->pn, sizeof(igtk->pn),
  127. - igtk->igtk, len) < 0) {
  128. - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  129. - "WPA: Failed to configure IGTK to the driver");
  130. - return -1;
  131. - }
  132. }
  133. return 0;
  134. @@ -2451,7 +2489,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
  135. */
  136. void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
  137. {
  138. - int clear_ptk = 1;
  139. + int clear_keys = 1;
  140. if (sm == NULL)
  141. return;
  142. @@ -2477,7 +2515,7 @@ void wpa_sm_notify_assoc(struct wpa_sm *
  143. /* Prepare for the next transition */
  144. wpa_ft_prepare_auth_request(sm, NULL);
  145. - clear_ptk = 0;
  146. + clear_keys = 0;
  147. }
  148. #endif /* CONFIG_IEEE80211R */
  149. #ifdef CONFIG_FILS
  150. @@ -2487,11 +2525,11 @@ void wpa_sm_notify_assoc(struct wpa_sm *
  151. * AUTHENTICATED state to get the EAPOL port Authorized.
  152. */
  153. wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
  154. - clear_ptk = 0;
  155. + clear_keys = 0;
  156. }
  157. #endif /* CONFIG_FILS */
  158. - if (clear_ptk) {
  159. + if (clear_keys) {
  160. /*
  161. * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
  162. * this is not part of a Fast BSS Transition.
  163. @@ -2501,6 +2539,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *
  164. os_memset(&sm->ptk, 0, sizeof(sm->ptk));
  165. sm->tptk_set = 0;
  166. os_memset(&sm->tptk, 0, sizeof(sm->tptk));
  167. + os_memset(&sm->gtk, 0, sizeof(sm->gtk));
  168. +#ifdef CONFIG_IEEE80211W
  169. + os_memset(&sm->igtk, 0, sizeof(sm->igtk));
  170. +#endif /* CONFIG_IEEE80211W */
  171. }
  172. #ifdef CONFIG_TDLS
  173. @@ -3052,6 +3094,10 @@ void wpa_sm_drop_sa(struct wpa_sm *sm)
  174. os_memset(sm->pmk, 0, sizeof(sm->pmk));
  175. os_memset(&sm->ptk, 0, sizeof(sm->ptk));
  176. os_memset(&sm->tptk, 0, sizeof(sm->tptk));
  177. + os_memset(&sm->gtk, 0, sizeof(sm->gtk));
  178. +#ifdef CONFIG_IEEE80211W
  179. + os_memset(&sm->igtk, 0, sizeof(sm->igtk));
  180. +#endif /* CONFIG_IEEE80211W */
  181. #ifdef CONFIG_IEEE80211R
  182. os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
  183. os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
  184. @@ -3124,29 +3170,11 @@ int wpa_wnmsleep_install_key(struct wpa_
  185. os_memset(&gd, 0, sizeof(gd));
  186. #ifdef CONFIG_IEEE80211W
  187. } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
  188. - struct wpa_igtk_kde igd;
  189. - u16 keyidx;
  190. + const struct wpa_igtk_kde *igtk;
  191. - os_memset(&igd, 0, sizeof(igd));
  192. - keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
  193. - os_memcpy(igd.keyid, buf + 2, 2);
  194. - os_memcpy(igd.pn, buf + 4, 6);
  195. -
  196. - keyidx = WPA_GET_LE16(igd.keyid);
  197. - os_memcpy(igd.igtk, buf + 10, keylen);
  198. -
  199. - wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
  200. - igd.igtk, keylen);
  201. - if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
  202. - broadcast_ether_addr,
  203. - keyidx, 0, igd.pn, sizeof(igd.pn),
  204. - igd.igtk, keylen) < 0) {
  205. - wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
  206. - "WNM mode");
  207. - os_memset(&igd, 0, sizeof(igd));
  208. + igtk = (const struct wpa_igtk_kde *) (buf + 2);
  209. + if (wpa_supplicant_install_igtk(sm, igtk) < 0)
  210. return -1;
  211. - }
  212. - os_memset(&igd, 0, sizeof(igd));
  213. #endif /* CONFIG_IEEE80211W */
  214. } else {
  215. wpa_printf(MSG_DEBUG, "Unknown element id");
  216. --- a/src/rsn_supp/wpa_i.h
  217. +++ b/src/rsn_supp/wpa_i.h
  218. @@ -31,6 +31,10 @@ struct wpa_sm {
  219. u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
  220. int rx_replay_counter_set;
  221. u8 request_counter[WPA_REPLAY_COUNTER_LEN];
  222. + struct wpa_gtk gtk;
  223. +#ifdef CONFIG_IEEE80211W
  224. + struct wpa_igtk igtk;
  225. +#endif /* CONFIG_IEEE80211W */
  226. struct eapol_sm *eapol; /* EAPOL state machine from upper level code */