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