1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 /* 20 * DOC: contains scan cache filter logic 21 */ 22 23 #include <wlan_scan_utils_api.h> 24 #include "wlan_scan_main.h" 25 #include "wlan_scan_cache_db_i.h" 26 #include <wlan_dfs_utils_api.h> 27 #include "wlan_crypto_global_def.h" 28 #include "wlan_crypto_global_api.h" 29 #include "wlan_reg_services_api.h" 30 31 /** 32 * scm_check_open() - Check if scan entry support open authmode 33 * @filter: scan filter 34 * @db_entry: db entry 35 * @security: matched security. 36 * 37 * Return: true if open security else false 38 */ 39 static bool scm_check_open(struct scan_filter *filter, 40 struct scan_cache_entry *db_entry, 41 struct security_info *security) 42 { 43 if (db_entry->cap_info.wlan_caps.privacy) { 44 scm_debug(QDF_MAC_ADDR_FMT" : have privacy set", 45 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 46 return false; 47 } 48 49 if (filter->ucastcipherset && 50 !(QDF_HAS_PARAM(filter->ucastcipherset, WLAN_CRYPTO_CIPHER_NONE))) { 51 scm_debug(QDF_MAC_ADDR_FMT" : Filter doesn't have CIPHER none in uc %x", 52 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 53 filter->ucastcipherset); 54 return false; 55 } 56 57 if (filter->mcastcipherset && 58 !(QDF_HAS_PARAM(filter->mcastcipherset, WLAN_CRYPTO_CIPHER_NONE))) { 59 scm_debug(QDF_MAC_ADDR_FMT" : Filter doesn't have CIPHER none in mc %x", 60 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 61 filter->mcastcipherset); 62 return false; 63 } 64 65 QDF_SET_PARAM(security->ucastcipherset, WLAN_CRYPTO_CIPHER_NONE); 66 QDF_SET_PARAM(security->mcastcipherset, WLAN_CRYPTO_CIPHER_NONE); 67 68 return true; 69 } 70 71 /** 72 * scm_check_wep() - Check if scan entry support WEP authmode 73 * @filter: scan filter 74 * @db_entry: db entry 75 * @security: matched security. 76 * 77 * Return: true if WEP security else false 78 */ 79 static bool scm_check_wep(struct scan_filter *filter, 80 struct scan_cache_entry *db_entry, 81 struct security_info *security) 82 { 83 /* If privacy bit is not set, consider no match */ 84 if (!db_entry->cap_info.wlan_caps.privacy) { 85 scm_debug(QDF_MAC_ADDR_FMT" : doesn't have privacy set", 86 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 87 return false; 88 } 89 90 if (!(db_entry->security_type & SCAN_SECURITY_TYPE_WEP)) { 91 scm_debug(QDF_MAC_ADDR_FMT" : doesn't support WEP", 92 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 93 return false; 94 } 95 96 if (!filter->ucastcipherset || !filter->mcastcipherset) { 97 scm_debug(QDF_MAC_ADDR_FMT" : Filter uc %x or mc %x cipher are 0", 98 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 99 filter->ucastcipherset, 100 filter->mcastcipherset); 101 return false; 102 } 103 104 if (!(QDF_HAS_PARAM(filter->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP) || 105 QDF_HAS_PARAM(filter->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP_40) || 106 QDF_HAS_PARAM(filter->ucastcipherset, 107 WLAN_CRYPTO_CIPHER_WEP_104))) { 108 scm_debug(QDF_MAC_ADDR_FMT" : Filter doesn't have WEP cipher in uc %x", 109 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 110 filter->ucastcipherset); 111 return false; 112 } 113 114 if (!(QDF_HAS_PARAM(filter->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP) || 115 QDF_HAS_PARAM(filter->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP_40) || 116 QDF_HAS_PARAM(filter->mcastcipherset, 117 WLAN_CRYPTO_CIPHER_WEP_104))) { 118 scm_debug(QDF_MAC_ADDR_FMT" : Filter doesn't have WEP cipher in mc %x", 119 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 120 filter->mcastcipherset); 121 return false; 122 } 123 124 if (QDF_HAS_PARAM(filter->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP)) 125 QDF_SET_PARAM(security->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP); 126 127 if (QDF_HAS_PARAM(filter->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP_40)) 128 QDF_SET_PARAM(security->ucastcipherset, 129 WLAN_CRYPTO_CIPHER_WEP_40); 130 131 if (QDF_HAS_PARAM(filter->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP_104)) 132 QDF_SET_PARAM(security->ucastcipherset, 133 WLAN_CRYPTO_CIPHER_WEP_104); 134 135 if (QDF_HAS_PARAM(filter->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP)) 136 QDF_SET_PARAM(security->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP); 137 138 if (QDF_HAS_PARAM(filter->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP_40)) 139 QDF_SET_PARAM(security->mcastcipherset, 140 WLAN_CRYPTO_CIPHER_WEP_40); 141 142 if (QDF_HAS_PARAM(filter->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP_104)) 143 QDF_SET_PARAM(security->mcastcipherset, 144 WLAN_CRYPTO_CIPHER_WEP_104); 145 146 return true; 147 } 148 149 /** 150 * scm_chk_if_cipher_n_akm_match() - Check if akm and ciphers match 151 * @filter: scan filter 152 * @ap_crypto: aps crypto params 153 * 154 * Return: true if matches 155 */ 156 static bool scm_chk_if_cipher_n_akm_match(struct scan_filter *filter, 157 struct wlan_crypto_params *ap_crypto) 158 { 159 /* Check AP's pairwise ciphers.*/ 160 if (!(filter->ucastcipherset & ap_crypto->ucastcipherset)) 161 return false; 162 163 /* Check AP's group cipher match.*/ 164 if (!(filter->mcastcipherset & ap_crypto->mcastcipherset)) 165 return false; 166 167 /* Check AP's AKM match with filter's AKM.*/ 168 if (!(filter->key_mgmt & ap_crypto->key_mgmt)) 169 return false; 170 171 /* Check AP's mgmt cipher match if present.*/ 172 if ((filter->mgmtcipherset && ap_crypto->mgmtcipherset) && 173 !(filter->mgmtcipherset & ap_crypto->mgmtcipherset)) 174 return false; 175 176 if (filter->ignore_pmf_cap) 177 return true; 178 179 if (filter->pmf_cap == WLAN_PMF_REQUIRED && 180 !(ap_crypto->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) 181 return false; 182 183 if (filter->pmf_cap == WLAN_PMF_DISABLED && 184 (ap_crypto->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) 185 return false; 186 187 return true; 188 } 189 190 static bool scm_chk_crypto_params(struct scan_filter *filter, 191 struct wlan_crypto_params *ap_crypto, 192 bool is_adaptive_11r, 193 struct scan_cache_entry *db_entry, 194 struct security_info *security) 195 { 196 if (!scm_chk_if_cipher_n_akm_match(filter, ap_crypto)) { 197 scm_debug(QDF_MAC_ADDR_FMT": fail. adaptive 11r %d Self: AKM %x CIPHER: mc %x uc %x mgmt %x pmf %d AP: AKM %x CIPHER: mc %x uc %x mgmt %x, RSN caps %x", 198 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), is_adaptive_11r, 199 filter->key_mgmt, filter->mcastcipherset, 200 filter->ucastcipherset, filter->mgmtcipherset, 201 filter->pmf_cap, ap_crypto->key_mgmt, 202 ap_crypto->mcastcipherset, ap_crypto->ucastcipherset, 203 ap_crypto->mgmtcipherset, ap_crypto->rsn_caps); 204 return false; 205 } 206 207 security->mcastcipherset = 208 ap_crypto->mcastcipherset & filter->mcastcipherset; 209 security->ucastcipherset = 210 ap_crypto->ucastcipherset & filter->ucastcipherset; 211 security->key_mgmt = ap_crypto->key_mgmt & filter->key_mgmt; 212 security->rsn_caps = ap_crypto->rsn_caps; 213 214 return true; 215 } 216 217 #ifdef WLAN_ADAPTIVE_11R 218 /** 219 * scm_check_and_update_adaptive_11r_key_mgmt_support() - check and update 220 * first rsn security which is present in RSN IE of Beacon/Probe response to 221 * corresponding FT AKM. 222 * @ap_crypto: crypto param structure 223 * 224 * Return: none 225 */ 226 static void scm_check_and_update_adaptive_11r_key_mgmt_support( 227 struct wlan_crypto_params *ap_crypto) 228 { 229 uint32_t i, first_key_mgmt = WLAN_CRYPTO_KEY_MGMT_MAX; 230 231 /* 232 * Supplicant compares AKM(s) in RSN IE of Beacon/Probe response and 233 * AKM on EAPOL M3 frame received by AP. In the case of multi AKM, 234 * previously Host converts all adaptive 11r AKM(s), if any, present 235 * in RSN IE of Beacon/Probe response to corresponding FT AKM but the 236 * AP(s) which support adaptive 11r (ADAPTIVE_11R_OUI: 0x964000) only 237 * converts first AKM to corresponding FT AKM and sends EAPOL M3 frame 238 * to DUT. This results in failure in a 4-way handshake in supplicant 239 * due to RSN IE miss-match between RSNIE sent by host and RSNIE 240 * present in EAPOL M3 frame. Now like AP, the host is converting only 241 * the first AKM to corresponding FT AKM to avoid RSNIE mismatch in 242 * supplicant. 243 */ 244 for (i = 0; i < WLAN_CRYPTO_KEY_MGMT_MAX; i++) { 245 if (ap_crypto->akm_list[i].key_mgmt == 246 WLAN_CRYPTO_KEY_MGMT_IEEE8021X || 247 ap_crypto->akm_list[i].key_mgmt == 248 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) { 249 first_key_mgmt = WLAN_CRYPTO_KEY_MGMT_IEEE8021X; 250 break; 251 } 252 253 if (ap_crypto->akm_list[i].key_mgmt == 254 WLAN_CRYPTO_KEY_MGMT_PSK || 255 ap_crypto->akm_list[i].key_mgmt == 256 WLAN_CRYPTO_KEY_MGMT_PSK_SHA256) { 257 first_key_mgmt = WLAN_CRYPTO_KEY_MGMT_PSK; 258 break; 259 } 260 } 261 262 if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_MAX) { 263 scm_debug("No adaptive 11r's AKM present in RSN IE"); 264 return; 265 } 266 267 if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_IEEE8021X) 268 QDF_SET_PARAM(ap_crypto->key_mgmt, 269 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X); 270 271 if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_PSK) 272 QDF_SET_PARAM(ap_crypto->key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK); 273 } 274 #else 275 static inline void scm_check_and_update_adaptive_11r_key_mgmt_support( 276 struct wlan_crypto_params *ap_crypto) 277 { 278 } 279 #endif 280 281 /** 282 * scm_check_rsn() - Check if scan entry support RSN security 283 * @filter: scan filter 284 * @db_entry: db entry 285 * @security: matched security. 286 * 287 * Return: true if RSN security else false 288 */ 289 static bool scm_check_rsn(struct scan_filter *filter, 290 struct scan_cache_entry *db_entry, 291 struct security_info *security) 292 { 293 bool is_adaptive_11r; 294 QDF_STATUS status; 295 struct wlan_crypto_params *ap_crypto; 296 bool match; 297 298 if (!util_scan_entry_rsn(db_entry)) { 299 scm_debug(QDF_MAC_ADDR_FMT" : doesn't have RSN IE", 300 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 301 return false; 302 } 303 304 ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto)); 305 if (!ap_crypto) 306 return false; 307 status = wlan_crypto_rsnie_check(ap_crypto, 308 util_scan_entry_rsn(db_entry)); 309 if (QDF_IS_STATUS_ERROR(status)) { 310 scm_err(QDF_MAC_ADDR_FMT": failed to parse RSN IE, status %d", 311 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status); 312 qdf_mem_free(ap_crypto); 313 return false; 314 } 315 316 is_adaptive_11r = db_entry->adaptive_11r_ap && 317 filter->enable_adaptive_11r; 318 319 /* If adaptive 11r is enabled set the FT AKM for AP */ 320 if (is_adaptive_11r) 321 scm_check_and_update_adaptive_11r_key_mgmt_support(ap_crypto); 322 323 match = scm_chk_crypto_params(filter, ap_crypto, is_adaptive_11r, 324 db_entry, security); 325 qdf_mem_free(ap_crypto); 326 327 return match; 328 } 329 330 /** 331 * scm_check_wpa() - Check if scan entry support WPA security 332 * @filter: scan filter 333 * @db_entry: db entry 334 * @security: matched security. 335 * 336 * Return: true if WPA security else false 337 */ 338 static bool scm_check_wpa(struct scan_filter *filter, 339 struct scan_cache_entry *db_entry, 340 struct security_info *security) 341 { 342 QDF_STATUS status; 343 struct wlan_crypto_params *ap_crypto; 344 bool match; 345 346 if (!util_scan_entry_wpa(db_entry)) { 347 scm_debug(QDF_MAC_ADDR_FMT" : doesn't have WPA IE", 348 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 349 return false; 350 } 351 352 ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto)); 353 if (!ap_crypto) 354 return false; 355 356 status = wlan_crypto_wpaie_check(ap_crypto, 357 util_scan_entry_wpa(db_entry)); 358 if (QDF_IS_STATUS_ERROR(status)) { 359 scm_err(QDF_MAC_ADDR_FMT": failed to parse WPA IE, status %d", 360 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status); 361 qdf_mem_free(ap_crypto); 362 return false; 363 } 364 365 match = scm_chk_crypto_params(filter, ap_crypto, false, 366 db_entry, security); 367 qdf_mem_free(ap_crypto); 368 369 return match; 370 } 371 372 /** 373 * scm_check_wapi() - Check if scan entry support WAPI security 374 * @filter: scan filter 375 * @db_entry: db entry 376 * @security: matched security. 377 * 378 * Return: true if WAPI security else false 379 */ 380 static bool scm_check_wapi(struct scan_filter *filter, 381 struct scan_cache_entry *db_entry, 382 struct security_info *security) 383 { 384 QDF_STATUS status; 385 struct wlan_crypto_params *ap_crypto; 386 387 if (!util_scan_entry_wapi(db_entry)) { 388 scm_debug(QDF_MAC_ADDR_FMT" : doesn't have WAPI IE", 389 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 390 return false; 391 } 392 393 ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto)); 394 if (!ap_crypto) 395 return false; 396 397 status = wlan_crypto_wapiie_check(ap_crypto, 398 util_scan_entry_wapi(db_entry)); 399 if (QDF_IS_STATUS_ERROR(status)) { 400 scm_err(QDF_MAC_ADDR_FMT": failed to parse WAPI IE, status %d", 401 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status); 402 qdf_mem_free(ap_crypto); 403 return false; 404 } 405 406 if (!scm_chk_if_cipher_n_akm_match(filter, ap_crypto)) { 407 scm_debug(QDF_MAC_ADDR_FMT": fail. Self: AKM %x CIPHER: mc %x uc %x mgmt %x pmf %d AP: AKM %x CIPHER: mc %x uc %x mgmt %x, RSN caps %x", 408 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), filter->key_mgmt, 409 filter->mcastcipherset, filter->ucastcipherset, 410 filter->mgmtcipherset, filter->pmf_cap, 411 ap_crypto->key_mgmt, ap_crypto->mcastcipherset, 412 ap_crypto->ucastcipherset, ap_crypto->mgmtcipherset, 413 ap_crypto->rsn_caps); 414 qdf_mem_free(ap_crypto); 415 416 return false; 417 } 418 419 security->mcastcipherset = 420 ap_crypto->mcastcipherset & filter->mcastcipherset; 421 security->ucastcipherset = 422 ap_crypto->ucastcipherset & filter->ucastcipherset; 423 security->key_mgmt = ap_crypto->key_mgmt & filter->key_mgmt; 424 security->rsn_caps = ap_crypto->rsn_caps; 425 qdf_mem_free(ap_crypto); 426 427 return true; 428 } 429 430 /** 431 * scm_match_any_security() - Check if any security in filter match 432 * @filter: scan filter 433 * @db_entry: db entry 434 * @security: matched security. 435 * 436 * Return: true if any security else false 437 */ 438 static bool scm_match_any_security(struct scan_filter *filter, 439 struct scan_cache_entry *db_entry, 440 struct security_info *security) 441 { 442 struct wlan_crypto_params *ap_crypto = {0}; 443 QDF_STATUS status; 444 bool match = false; 445 446 ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto)); 447 if (!ap_crypto) 448 return match; 449 450 if (util_scan_entry_rsn(db_entry)) { 451 status = wlan_crypto_rsnie_check(ap_crypto, 452 util_scan_entry_rsn(db_entry)); 453 if (QDF_IS_STATUS_ERROR(status)) { 454 scm_err(QDF_MAC_ADDR_FMT": failed to parse RSN IE, status %d", 455 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status); 456 goto free; 457 } 458 security->mcastcipherset = ap_crypto->mcastcipherset; 459 security->ucastcipherset = ap_crypto->ucastcipherset; 460 security->key_mgmt = ap_crypto->key_mgmt; 461 security->rsn_caps = ap_crypto->rsn_caps; 462 QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_RSNA); 463 match = true; 464 goto free; 465 } 466 467 if (util_scan_entry_wpa(db_entry)) { 468 status = wlan_crypto_wpaie_check(ap_crypto, 469 util_scan_entry_wpa(db_entry)); 470 if (QDF_IS_STATUS_ERROR(status)) { 471 scm_err(QDF_MAC_ADDR_FMT": failed to parse WPA IE, status %d", 472 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status); 473 goto free; 474 } 475 security->mcastcipherset = ap_crypto->mcastcipherset; 476 security->ucastcipherset = ap_crypto->ucastcipherset; 477 security->key_mgmt = ap_crypto->key_mgmt; 478 security->rsn_caps = ap_crypto->rsn_caps; 479 QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_WPA); 480 match = true; 481 goto free; 482 } 483 484 if (util_scan_entry_wapi(db_entry)) { 485 status = wlan_crypto_wapiie_check(ap_crypto, 486 util_scan_entry_wapi(db_entry)); 487 if (QDF_IS_STATUS_ERROR(status)) { 488 scm_err(QDF_MAC_ADDR_FMT": failed to parse WPA IE, status %d", 489 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 490 status); 491 goto free; 492 } 493 security->mcastcipherset = ap_crypto->mcastcipherset; 494 security->ucastcipherset = ap_crypto->ucastcipherset; 495 security->key_mgmt = ap_crypto->key_mgmt; 496 security->rsn_caps = ap_crypto->rsn_caps; 497 QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_WAPI); 498 match = true; 499 goto free; 500 } 501 502 if (db_entry->cap_info.wlan_caps.privacy) { 503 QDF_SET_PARAM(security->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP); 504 QDF_SET_PARAM(security->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP); 505 QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_SHARED); 506 match = true; 507 goto free; 508 } 509 510 QDF_SET_PARAM(security->ucastcipherset, WLAN_CRYPTO_CIPHER_NONE); 511 QDF_SET_PARAM(security->mcastcipherset, WLAN_CRYPTO_CIPHER_NONE); 512 QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_OPEN); 513 match = true; 514 515 free: 516 qdf_mem_free(ap_crypto); 517 518 return match; 519 } 520 521 /** 522 * scm_is_security_match() - Check if security in filter match 523 * @filter: scan filter 524 * @db_entry: db entry 525 * @security: matched security. 526 * 527 * Return: true if security match else false 528 */ 529 static bool scm_is_security_match(struct scan_filter *filter, 530 struct scan_cache_entry *db_entry, 531 struct security_info *security) 532 { 533 int i; 534 bool match = false; 535 536 if (!filter->authmodeset) 537 return scm_match_any_security(filter, db_entry, security); 538 539 for (i = 0; i < WLAN_CRYPTO_AUTH_MAX && !match; i++) { 540 if (!QDF_HAS_PARAM(filter->authmodeset, i)) 541 continue; 542 543 security->authmodeset = 0; 544 QDF_SET_PARAM(security->authmodeset, i); 545 546 switch (i) { 547 case WLAN_CRYPTO_AUTH_NONE: 548 case WLAN_CRYPTO_AUTH_OPEN: 549 case WLAN_CRYPTO_AUTH_AUTO: 550 match = scm_check_open(filter, db_entry, security); 551 if (match) 552 break; 553 /* If not OPEN, then check WEP match */ 554 fallthrough; 555 case WLAN_CRYPTO_AUTH_SHARED: 556 match = scm_check_wep(filter, db_entry, security); 557 break; 558 case WLAN_CRYPTO_AUTH_8021X: 559 case WLAN_CRYPTO_AUTH_RSNA: 560 case WLAN_CRYPTO_AUTH_CCKM: 561 case WLAN_CRYPTO_AUTH_SAE: 562 case WLAN_CRYPTO_AUTH_FILS_SK: 563 /* First check if there is a RSN match */ 564 match = scm_check_rsn(filter, db_entry, security); 565 break; 566 case WLAN_CRYPTO_AUTH_WPA: 567 match = scm_check_wpa(filter, db_entry, security); 568 break; 569 case WLAN_CRYPTO_AUTH_WAPI:/* WAPI */ 570 match = scm_check_wapi(filter, db_entry, security); 571 break; 572 default: 573 break; 574 } 575 } 576 577 return match; 578 } 579 580 static bool scm_ignore_ssid_check_for_owe(struct scan_filter *filter, 581 struct scan_cache_entry *db_entry) 582 { 583 bool is_hidden; 584 585 is_hidden = util_scan_entry_is_hidden_ap(db_entry); 586 if (is_hidden && 587 QDF_HAS_PARAM(filter->key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE) && 588 util_is_bssid_match(&filter->bssid_hint, &db_entry->bssid)) 589 return true; 590 591 /* Dump only for hidden SSID as non-hidden are anyway rejected */ 592 if (is_hidden && !qdf_is_macaddr_zero(&filter->bssid_hint)) 593 scm_debug(QDF_MAC_ADDR_FMT ": Ignore hidden AP as key_mgmt 0x%x is not OWE or bssid hint: " 594 QDF_MAC_ADDR_FMT " does not match", 595 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 596 filter->key_mgmt, 597 QDF_MAC_ADDR_REF(filter->bssid_hint.bytes)); 598 return false; 599 } 600 601 #ifdef WLAN_FEATURE_FILS_SK 602 /** 603 * scm_is_fils_config_match() - Check if FILS config matches 604 * @filter: scan filter 605 * @db_entry: db entry 606 * 607 * Return: true if FILS config matches else false 608 */ 609 static bool scm_is_fils_config_match(struct scan_filter *filter, 610 struct scan_cache_entry *db_entry) 611 { 612 int i; 613 struct fils_indication_ie *indication_ie; 614 uint8_t *data; 615 uint8_t *end_ptr; 616 617 if (!filter->fils_scan_filter.realm_check) 618 return true; 619 620 if (!db_entry->ie_list.fils_indication) 621 return false; 622 623 indication_ie = 624 (struct fils_indication_ie *)db_entry->ie_list.fils_indication; 625 626 /* 627 * Don't validate the realm, if AP advertises realm count as 0 628 * in the FILS indication element 629 */ 630 if (!indication_ie->realm_identifiers_cnt) 631 return true; 632 633 end_ptr = (uint8_t *)indication_ie + indication_ie->len + 2; 634 data = indication_ie->variable_data; 635 636 if (indication_ie->is_cache_id_present && 637 (data + CACHE_IDENTIFIER_LEN) <= end_ptr) 638 data += CACHE_IDENTIFIER_LEN; 639 640 if (indication_ie->is_hessid_present && 641 (data + HESSID_LEN) <= end_ptr) 642 data += HESSID_LEN; 643 644 for (i = 1; i <= indication_ie->realm_identifiers_cnt && 645 (data + REALM_HASH_LEN) <= end_ptr; i++) { 646 if (!qdf_mem_cmp(filter->fils_scan_filter.fils_realm, 647 data, REALM_HASH_LEN)) 648 return true; 649 /* Max realm count reached */ 650 if (indication_ie->realm_identifiers_cnt == i) 651 break; 652 653 data = data + REALM_HASH_LEN; 654 } 655 656 return false; 657 } 658 659 #else 660 661 static inline bool scm_is_fils_config_match(struct scan_filter *filter, 662 struct scan_cache_entry *db_entry) 663 { 664 return true; 665 } 666 #endif 667 668 static bool scm_check_dot11mode(struct scan_cache_entry *db_entry, 669 struct scan_filter *filter) 670 { 671 switch (filter->dot11mode) { 672 case ALLOW_ALL: 673 break; 674 case ALLOW_11N_ONLY: 675 if (!util_scan_entry_htcap(db_entry)) 676 return false; 677 break; 678 case ALLOW_11AC_ONLY: 679 if (!util_scan_entry_vhtcap(db_entry)) 680 return false; 681 break; 682 case ALLOW_11AX_ONLY: 683 if (!util_scan_entry_hecap(db_entry)) 684 return false; 685 break; 686 case ALLOW_11BE_ONLY: 687 if (!util_scan_entry_ehtcap(db_entry)) 688 return false; 689 break; 690 default: 691 scm_debug("Invalid dot11mode filter passed %d", 692 filter->dot11mode); 693 } 694 695 return true; 696 } 697 698 #ifdef WLAN_FEATURE_11BE_MLO 699 static bool scm_mlo_filter_match(struct wlan_objmgr_pdev *pdev, 700 struct scan_filter *filter, 701 struct scan_cache_entry *db_entry) 702 { 703 uint8_t i, band_bitmap, assoc_band_bitmap; 704 enum reg_wifi_band band; 705 struct partner_link_info *partner_link; 706 bool is_disabled; 707 struct qdf_mac_addr *mld_addr; 708 709 /* If MLD address of scan entry doesn't match the MLD address in scan 710 * filter, then drop the scan entry even if the BSSID matches. 711 * This is to filter out entries from APs with similar BSSID 712 * but different MLD address. 713 */ 714 if (filter->match_mld_addr) { 715 mld_addr = util_scan_entry_mldaddr(db_entry); 716 if (!mld_addr || 717 !qdf_is_macaddr_equal(&filter->mld_addr, mld_addr)) { 718 scm_debug("Scan filter MLD mismatch " QDF_MAC_ADDR_FMT, 719 QDF_MAC_ADDR_REF(filter->mld_addr.bytes)); 720 return false; 721 } 722 } 723 724 if (!db_entry->ie_list.multi_link_bv) 725 return true; 726 if (!filter->band_bitmap) 727 return true; 728 729 /* Apply assoc band filter only for assoc link */ 730 band_bitmap = filter->band_bitmap & 0xf; 731 assoc_band_bitmap = (filter->band_bitmap & 0xf0) >> 4; 732 band = wlan_reg_freq_to_band(db_entry->channel.chan_freq); 733 if ((assoc_band_bitmap && !(band_bitmap & BIT(band) & assoc_band_bitmap)) || 734 (!assoc_band_bitmap && !(band_bitmap & BIT(band)))) { 735 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as bss freq %d not match band bitmap: 0x%x", 736 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 737 db_entry->channel.chan_freq, filter->band_bitmap); 738 return false; 739 } 740 for (i = 0; i < db_entry->ml_info.num_links; i++) { 741 partner_link = &db_entry->ml_info.link_info[i]; 742 band = wlan_reg_freq_to_band(partner_link->freq); 743 744 is_disabled = wlan_reg_is_disable_for_pwrmode( 745 pdev, 746 partner_link->freq, 747 REG_BEST_PWR_MODE); 748 if (is_disabled) { 749 scm_debug(QDF_MAC_ADDR_FMT ": Partner " QDF_MAC_ADDR_FMT " link id %d freq %d disabled", 750 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 751 QDF_MAC_ADDR_REF( 752 partner_link->link_addr.bytes), 753 partner_link->link_id, 754 partner_link->freq); 755 continue; 756 } 757 if (band_bitmap & BIT(band)) 758 partner_link->is_valid_link = true; 759 } 760 761 return true; 762 } 763 #else 764 static inline bool scm_mlo_filter_match(struct wlan_objmgr_pdev *pdev, 765 struct scan_filter *filter, 766 struct scan_cache_entry *db_entry) 767 { 768 return true; 769 } 770 #endif 771 772 #ifdef WLAN_FEATURE_11BE 773 774 /** 775 * scm_eht_puncture_valid(): The function finds the puncturing pattern from the 776 * IE. If the primary channel is in the punctured list then the channel cannot 777 * be used, and this function returns false/invalid. 778 * @pdev: pdev device. 779 * @db_entry: scan cache entry which will indicate EHT ops. 780 * 781 * Return - false if the primary channel is punctured and true if otherwise. 782 */ 783 static bool scm_eht_puncture_valid(struct wlan_objmgr_pdev *pdev, 784 struct scan_cache_entry *db_entry) 785 { 786 struct wlan_ie_ehtops *eht_ops; 787 int8_t orig_width; 788 enum phy_ch_width width; 789 qdf_freq_t center_freq_320m; 790 uint16_t orig_puncture_bitmap; 791 uint16_t new_puncture_bitmap = 0; 792 QDF_STATUS status; 793 uint32_t cfreq1; 794 uint8_t band_mask; 795 796 eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(db_entry); 797 if (!eht_ops) 798 return true; 799 if (!QDF_GET_BITS(eht_ops->ehtop_param, 800 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) 801 return true; 802 if (QDF_GET_BITS(eht_ops->ehtop_param, 803 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_IDX, 804 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_BITS)) { 805 orig_puncture_bitmap = 806 QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[0], 807 0, 8); 808 orig_puncture_bitmap |= 809 QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[1], 810 0, 8) << 8; 811 } else { 812 orig_puncture_bitmap = 0; 813 } 814 if (!orig_puncture_bitmap) 815 return true; 816 817 orig_width = QDF_GET_BITS(eht_ops->control, 818 EHTOP_INFO_CHAN_WIDTH_IDX, 819 EHTOP_INFO_CHAN_WIDTH_BITS); 820 821 band_mask = BIT(wlan_reg_freq_to_band(db_entry->channel.chan_freq)); 822 823 /* Check if CCFS bits are present */ 824 if (QDF_GET_BITS(eht_ops->ehtop_param, 825 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) 826 cfreq1 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs1, 827 band_mask); 828 else 829 cfreq1 = 0; 830 831 if (orig_width == WLAN_EHT_CHWIDTH_320) { 832 width = CH_WIDTH_320MHZ; 833 center_freq_320m = cfreq1; 834 } else { 835 width = orig_width; 836 center_freq_320m = 0; 837 } 838 839 /* Find if the primary channel is punctured */ 840 status = wlan_reg_extract_puncture_by_bw(width, 841 orig_puncture_bitmap, 842 db_entry->channel.chan_freq, 843 center_freq_320m, 844 CH_WIDTH_20MHZ, 845 &new_puncture_bitmap); 846 if (QDF_IS_STATUS_ERROR(status) || new_puncture_bitmap) { 847 scm_debug(QDF_MAC_ADDR_FMT "freq %d width %d 320m center %d puncture: orig %d new %d status %d", 848 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 849 db_entry->channel.chan_freq, width, center_freq_320m, 850 orig_puncture_bitmap, new_puncture_bitmap, status); 851 return false; 852 } else { 853 return true; 854 } 855 } 856 #else 857 static inline bool scm_eht_puncture_valid(struct wlan_objmgr_pdev *pdev, 858 struct scan_cache_entry *db_entry) 859 { 860 return true; 861 } 862 #endif 863 864 bool scm_filter_match(struct wlan_objmgr_psoc *psoc, 865 struct scan_cache_entry *db_entry, 866 struct scan_filter *filter, 867 struct security_info *security) 868 { 869 int i; 870 bool match = false; 871 struct scan_default_params *def_param; 872 struct wlan_objmgr_pdev *pdev; 873 874 def_param = wlan_scan_psoc_get_def_params(psoc); 875 if (!def_param) 876 return false; 877 878 if (db_entry->ssid.length) { 879 for (i = 0; i < filter->num_of_ssid; i++) { 880 if (util_is_ssid_match(&filter->ssid_list[i], 881 &db_entry->ssid)) { 882 match = true; 883 break; 884 } 885 } 886 } 887 /* 888 * In OWE transition mode, ssid is hidden. And supplicant does not issue 889 * scan with specific ssid prior to connect as in other hidden ssid 890 * cases. Add explicit check to allow OWE when ssid is hidden. 891 */ 892 if (!match) 893 match = scm_ignore_ssid_check_for_owe(filter, db_entry); 894 895 if (!match && filter->num_of_ssid) 896 return false; 897 898 match = false; 899 for (i = 0; i < filter->num_of_bssid; i++) { 900 if (util_is_bssid_match(&filter->bssid_list[i], 901 &db_entry->bssid)) { 902 match = true; 903 break; 904 } 905 } 906 907 if (!match && filter->num_of_bssid) { 908 /* 909 * Do not print if ssid is not present in filter to avoid 910 * excessive prints 911 */ 912 if (filter->num_of_ssid) 913 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as BSSID not in list (no. of BSSID in list %d)", 914 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 915 filter->num_of_bssid); 916 return false; 917 } 918 919 if (filter->age_threshold && 920 filter->age_threshold < util_scan_entry_age(db_entry)) { 921 /* 922 * Do not print if bssid/ssid is not present in filter to avoid 923 * excessive prints 924 */ 925 if (filter->num_of_bssid || filter->num_of_ssid) 926 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as age %lu ms is greater than threshold %lu ms", 927 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 928 util_scan_entry_age(db_entry), 929 filter->age_threshold); 930 return false; 931 } 932 933 if (filter->dot11mode && !scm_check_dot11mode(db_entry, filter)) { 934 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as dot11mode %d didn't match phymode %d", 935 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 936 filter->dot11mode, db_entry->phy_mode); 937 return false; 938 } 939 940 if (filter->ignore_6ghz_channel && 941 WLAN_REG_IS_6GHZ_CHAN_FREQ(db_entry->channel.chan_freq)) { 942 /* 943 * Do not print if bssid/ssid is not present in filter to avoid 944 * excessive prints 945 */ 946 if (filter->num_of_bssid || filter->num_of_ssid) 947 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as its on 6Ghz freq %d", 948 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 949 db_entry->channel.chan_freq); 950 951 return false; 952 } 953 954 pdev = wlan_objmgr_get_pdev_by_id(psoc, db_entry->pdev_id, 955 WLAN_SCAN_ID); 956 if (!pdev) { 957 scm_err(QDF_MAC_ADDR_FMT ": Ignore as pdev not found", 958 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 959 return false; 960 } 961 962 if (filter->ignore_nol_chan && 963 utils_dfs_is_freq_in_nol(pdev, db_entry->channel.chan_freq)) { 964 wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); 965 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as chan in NOL list", 966 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 967 return false; 968 } 969 wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); 970 971 match = false; 972 for (i = 0; i < filter->num_of_channels; i++) { 973 if (!filter->chan_freq_list[i] || 974 filter->chan_freq_list[i] == 975 db_entry->channel.chan_freq) { 976 match = true; 977 break; 978 } 979 } 980 981 if (!match && filter->num_of_channels) { 982 /* 983 * Do not print if bssid/ssid is not present in filter to avoid 984 * excessive prints (e.g RRM case where only freq list is 985 * provided to get AP's in specific frequencies) 986 */ 987 if (filter->num_of_bssid || filter->num_of_ssid) 988 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as AP's freq %d is not in freq list", 989 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 990 db_entry->channel.chan_freq); 991 return false; 992 } 993 994 if (filter->rrm_measurement_filter) 995 return true; 996 997 if (!filter->ignore_auth_enc_type && !filter->match_security_func && 998 !scm_is_security_match(filter, db_entry, security)) { 999 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as security profile didn't match", 1000 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 1001 return false; 1002 } 1003 1004 if (filter->match_security_func && 1005 !filter->match_security_func(filter->match_security_func_arg, 1006 db_entry)) { 1007 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as custom security match failed", 1008 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 1009 return false; 1010 } 1011 1012 if (filter->ccx_validate_bss && 1013 !filter->ccx_validate_bss(filter->ccx_validate_bss_arg, 1014 db_entry, 0)) { 1015 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as CCX validateion failed", 1016 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 1017 return false; 1018 } 1019 1020 if (!util_is_bss_type_match(filter->bss_type, db_entry->cap_info)) { 1021 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as bss type didn't match cap_info %x bss_type %d", 1022 QDF_MAC_ADDR_REF(db_entry->bssid.bytes), 1023 db_entry->cap_info.value, filter->bss_type); 1024 return false; 1025 } 1026 1027 /* Match realm */ 1028 if (!scm_is_fils_config_match(filter, db_entry)) { 1029 scm_debug(QDF_MAC_ADDR_FMT ":Ignore as fils config didn't match", 1030 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 1031 return false; 1032 } 1033 1034 if (!util_mdie_match(filter->mobility_domain, 1035 (struct rsn_mdie *)db_entry->ie_list.mdie)) { 1036 scm_debug(QDF_MAC_ADDR_FMT ": Ignore as mdie didn't match", 1037 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 1038 return false; 1039 } 1040 1041 if (!scm_mlo_filter_match(pdev, filter, db_entry)) 1042 return false; 1043 1044 pdev = wlan_objmgr_get_pdev_by_id(psoc, db_entry->pdev_id, 1045 WLAN_SCAN_ID); 1046 if (!pdev) { 1047 scm_err(QDF_MAC_ADDR_FMT ": Ignore as pdev not found", 1048 QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); 1049 return false; 1050 } 1051 if (!scm_eht_puncture_valid(pdev, db_entry)) { 1052 wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); 1053 return false; 1054 } 1055 wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); 1056 1057 return true; 1058 } 1059