mfp.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * KUnit tests for management frame acceptance
  4. *
  5. * Copyright (C) 2023 Intel Corporation
  6. */
  7. #include <kunit/test.h>
  8. #include <kunit/skbuff.h>
  9. #include "../ieee80211_i.h"
  10. #include "../sta_info.h"
  11. MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
  12. static const struct mfp_test_case {
  13. const char *desc;
  14. bool sta, mfp, decrypted, unicast, assoc;
  15. u8 category;
  16. u8 stype;
  17. u8 action;
  18. ieee80211_rx_result result;
  19. } accept_mfp_cases[] = {
  20. /* regular public action */
  21. {
  22. .desc = "public action: accept unicast from unknown peer",
  23. .stype = IEEE80211_STYPE_ACTION,
  24. .category = WLAN_CATEGORY_PUBLIC,
  25. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  26. .unicast = true,
  27. .result = RX_CONTINUE,
  28. },
  29. {
  30. .desc = "public action: accept multicast from unknown peer",
  31. .stype = IEEE80211_STYPE_ACTION,
  32. .category = WLAN_CATEGORY_PUBLIC,
  33. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  34. .unicast = false,
  35. .result = RX_CONTINUE,
  36. },
  37. {
  38. .desc = "public action: accept unicast without MFP",
  39. .stype = IEEE80211_STYPE_ACTION,
  40. .category = WLAN_CATEGORY_PUBLIC,
  41. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  42. .unicast = true,
  43. .sta = true,
  44. .result = RX_CONTINUE,
  45. },
  46. {
  47. .desc = "public action: accept multicast without MFP",
  48. .stype = IEEE80211_STYPE_ACTION,
  49. .category = WLAN_CATEGORY_PUBLIC,
  50. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  51. .unicast = false,
  52. .sta = true,
  53. .result = RX_CONTINUE,
  54. },
  55. {
  56. .desc = "public action: drop unicast with MFP",
  57. .stype = IEEE80211_STYPE_ACTION,
  58. .category = WLAN_CATEGORY_PUBLIC,
  59. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  60. .unicast = true,
  61. .sta = true,
  62. .mfp = true,
  63. .result = RX_DROP_U_UNPROT_UNICAST_PUB_ACTION,
  64. },
  65. {
  66. .desc = "public action: accept multicast with MFP",
  67. .stype = IEEE80211_STYPE_ACTION,
  68. .category = WLAN_CATEGORY_PUBLIC,
  69. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  70. .unicast = false,
  71. .sta = true,
  72. .mfp = true,
  73. .result = RX_CONTINUE,
  74. },
  75. /* protected dual of public action */
  76. {
  77. .desc = "protected dual: drop unicast from unknown peer",
  78. .stype = IEEE80211_STYPE_ACTION,
  79. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  80. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  81. .unicast = true,
  82. .result = RX_DROP_U_UNPROT_DUAL,
  83. },
  84. {
  85. .desc = "protected dual: drop multicast from unknown peer",
  86. .stype = IEEE80211_STYPE_ACTION,
  87. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  88. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  89. .unicast = false,
  90. .result = RX_DROP_U_UNPROT_DUAL,
  91. },
  92. {
  93. .desc = "protected dual: drop unicast without MFP",
  94. .stype = IEEE80211_STYPE_ACTION,
  95. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  96. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  97. .unicast = true,
  98. .sta = true,
  99. .result = RX_DROP_U_UNPROT_DUAL,
  100. },
  101. {
  102. .desc = "protected dual: drop multicast without MFP",
  103. .stype = IEEE80211_STYPE_ACTION,
  104. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  105. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  106. .unicast = false,
  107. .sta = true,
  108. .result = RX_DROP_U_UNPROT_DUAL,
  109. },
  110. {
  111. .desc = "protected dual: drop undecrypted unicast with MFP",
  112. .stype = IEEE80211_STYPE_ACTION,
  113. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  114. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  115. .unicast = true,
  116. .sta = true,
  117. .mfp = true,
  118. .result = RX_DROP_U_UNPROT_DUAL,
  119. },
  120. {
  121. .desc = "protected dual: drop undecrypted multicast with MFP",
  122. .stype = IEEE80211_STYPE_ACTION,
  123. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  124. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  125. .unicast = false,
  126. .sta = true,
  127. .mfp = true,
  128. .result = RX_DROP_U_UNPROT_DUAL,
  129. },
  130. {
  131. .desc = "protected dual: accept unicast with MFP",
  132. .stype = IEEE80211_STYPE_ACTION,
  133. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  134. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  135. .decrypted = true,
  136. .unicast = true,
  137. .sta = true,
  138. .mfp = true,
  139. .result = RX_CONTINUE,
  140. },
  141. {
  142. .desc = "protected dual: accept multicast with MFP",
  143. .stype = IEEE80211_STYPE_ACTION,
  144. .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
  145. .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
  146. .decrypted = true,
  147. .unicast = false,
  148. .sta = true,
  149. .mfp = true,
  150. .result = RX_CONTINUE,
  151. },
  152. /* deauth/disassoc before keys are set */
  153. {
  154. .desc = "deauth: accept unicast with MFP but w/o key",
  155. .stype = IEEE80211_STYPE_DEAUTH,
  156. .sta = true,
  157. .mfp = true,
  158. .unicast = true,
  159. .result = RX_CONTINUE,
  160. },
  161. {
  162. .desc = "disassoc: accept unicast with MFP but w/o key",
  163. .stype = IEEE80211_STYPE_DEAUTH,
  164. .sta = true,
  165. .mfp = true,
  166. .unicast = true,
  167. .result = RX_CONTINUE,
  168. },
  169. /* non-public robust action frame ... */
  170. {
  171. .desc = "BA action: drop unicast before assoc",
  172. .stype = IEEE80211_STYPE_ACTION,
  173. .category = WLAN_CATEGORY_BACK,
  174. .unicast = true,
  175. .sta = true,
  176. .result = RX_DROP_U_UNPROT_ROBUST_ACTION,
  177. },
  178. {
  179. .desc = "BA action: drop unprotected after assoc",
  180. .stype = IEEE80211_STYPE_ACTION,
  181. .category = WLAN_CATEGORY_BACK,
  182. .unicast = true,
  183. .sta = true,
  184. .mfp = true,
  185. .result = RX_DROP_U_UNPROT_UCAST_MGMT,
  186. },
  187. {
  188. .desc = "BA action: accept unprotected without MFP",
  189. .stype = IEEE80211_STYPE_ACTION,
  190. .category = WLAN_CATEGORY_BACK,
  191. .unicast = true,
  192. .sta = true,
  193. .assoc = true,
  194. .mfp = false,
  195. .result = RX_CONTINUE,
  196. },
  197. {
  198. .desc = "BA action: drop unprotected with MFP",
  199. .stype = IEEE80211_STYPE_ACTION,
  200. .category = WLAN_CATEGORY_BACK,
  201. .unicast = true,
  202. .sta = true,
  203. .mfp = true,
  204. .result = RX_DROP_U_UNPROT_UCAST_MGMT,
  205. },
  206. };
  207. KUNIT_ARRAY_PARAM_DESC(accept_mfp, accept_mfp_cases, desc);
  208. static void accept_mfp(struct kunit *test)
  209. {
  210. static struct sta_info sta;
  211. const struct mfp_test_case *params = test->param_value;
  212. struct ieee80211_rx_data rx = {
  213. .sta = params->sta ? &sta : NULL,
  214. };
  215. struct ieee80211_rx_status *status;
  216. struct ieee80211_hdr_3addr hdr = {
  217. .frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
  218. params->stype),
  219. .addr1 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
  220. .addr2 = { 0x12, 0x22, 0x33, 0x44, 0x55, 0x66 },
  221. /* A3/BSSID doesn't matter here */
  222. };
  223. memset(&sta, 0, sizeof(sta));
  224. if (!params->sta) {
  225. KUNIT_ASSERT_FALSE(test, params->mfp);
  226. KUNIT_ASSERT_FALSE(test, params->decrypted);
  227. }
  228. if (params->mfp)
  229. set_sta_flag(&sta, WLAN_STA_MFP);
  230. if (params->assoc)
  231. set_bit(WLAN_STA_ASSOC, &sta._flags);
  232. rx.skb = kunit_zalloc_skb(test, 128, GFP_KERNEL);
  233. KUNIT_ASSERT_NOT_NULL(test, rx.skb);
  234. status = IEEE80211_SKB_RXCB(rx.skb);
  235. if (params->decrypted) {
  236. status->flag |= RX_FLAG_DECRYPTED;
  237. if (params->unicast)
  238. hdr.frame_control |=
  239. cpu_to_le16(IEEE80211_FCTL_PROTECTED);
  240. }
  241. if (params->unicast)
  242. hdr.addr1[0] = 0x02;
  243. skb_put_data(rx.skb, &hdr, sizeof(hdr));
  244. switch (params->stype) {
  245. case IEEE80211_STYPE_ACTION:
  246. skb_put_u8(rx.skb, params->category);
  247. skb_put_u8(rx.skb, params->action);
  248. break;
  249. case IEEE80211_STYPE_DEAUTH:
  250. case IEEE80211_STYPE_DISASSOC: {
  251. __le16 reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
  252. skb_put_data(rx.skb, &reason, sizeof(reason));
  253. }
  254. break;
  255. }
  256. KUNIT_EXPECT_EQ(test,
  257. (__force u32)ieee80211_drop_unencrypted_mgmt(&rx),
  258. (__force u32)params->result);
  259. }
  260. static struct kunit_case mfp_test_cases[] = {
  261. KUNIT_CASE_PARAM(accept_mfp, accept_mfp_gen_params),
  262. {}
  263. };
  264. static struct kunit_suite mfp = {
  265. .name = "mac80211-mfp",
  266. .test_cases = mfp_test_cases,
  267. };
  268. kunit_test_suite(mfp);