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 */
scm_check_open(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_check_wep(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_chk_if_cipher_n_akm_match(struct scan_filter * filter,struct wlan_crypto_params * ap_crypto)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
scm_chk_crypto_params(struct scan_filter * filter,struct wlan_crypto_params * ap_crypto,bool is_adaptive_11r,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_check_and_update_adaptive_11r_key_mgmt_support(struct wlan_crypto_params * ap_crypto)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
scm_check_and_update_adaptive_11r_key_mgmt_support(struct wlan_crypto_params * ap_crypto)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 */
scm_check_rsn(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_check_wpa(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_check_wapi(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_match_any_security(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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 */
scm_is_security_match(struct scan_filter * filter,struct scan_cache_entry * db_entry,struct security_info * security)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
scm_ignore_ssid_check_for_owe(struct scan_filter * filter,struct scan_cache_entry * db_entry)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 */
scm_is_fils_config_match(struct scan_filter * filter,struct scan_cache_entry * db_entry)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
scm_is_fils_config_match(struct scan_filter * filter,struct scan_cache_entry * db_entry)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
scm_check_dot11mode(struct scan_cache_entry * db_entry,struct scan_filter * filter)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
scm_mlo_filter_match(struct wlan_objmgr_pdev * pdev,struct scan_filter * filter,struct scan_cache_entry * db_entry)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
scm_mlo_filter_match(struct wlan_objmgr_pdev * pdev,struct scan_filter * filter,struct scan_cache_entry * db_entry)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 */
scm_eht_puncture_valid(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * db_entry)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
scm_eht_puncture_valid(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * db_entry)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
scm_filter_match(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * db_entry,struct scan_filter * filter,struct security_info * security)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