xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_filter.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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 	scm_debug("First AKM:%d present in RSN IE of bcn/Probe rsp at index:%d",
268 		  first_key_mgmt, i);
269 
270 	if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_IEEE8021X)
271 		QDF_SET_PARAM(ap_crypto->key_mgmt,
272 			      WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X);
273 
274 	if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_PSK)
275 		QDF_SET_PARAM(ap_crypto->key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK);
276 }
277 #else
278 static inline void scm_check_and_update_adaptive_11r_key_mgmt_support(
279 					struct wlan_crypto_params *ap_crypto)
280 {
281 }
282 #endif
283 
284 /**
285  * scm_check_rsn() - Check if scan entry support RSN security
286  * @filter: scan filter
287  * @db_entry: db entry
288  * @security: matched security.
289  *
290  * Return: true if RSN security else false
291  */
292 static bool scm_check_rsn(struct scan_filter *filter,
293 			  struct scan_cache_entry *db_entry,
294 			  struct security_info *security)
295 {
296 	bool is_adaptive_11r;
297 	QDF_STATUS status;
298 	struct wlan_crypto_params *ap_crypto;
299 	bool match;
300 
301 	if (!util_scan_entry_rsn(db_entry)) {
302 		scm_debug(QDF_MAC_ADDR_FMT" : doesn't have RSN IE",
303 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
304 		return false;
305 	}
306 
307 	ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto));
308 	if (!ap_crypto)
309 		return false;
310 	status = wlan_crypto_rsnie_check(ap_crypto,
311 					 util_scan_entry_rsn(db_entry));
312 	if (QDF_IS_STATUS_ERROR(status)) {
313 		scm_err(QDF_MAC_ADDR_FMT": failed to parse RSN IE, status %d",
314 			QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status);
315 		qdf_mem_free(ap_crypto);
316 		return false;
317 	}
318 
319 	is_adaptive_11r = db_entry->adaptive_11r_ap &&
320 				filter->enable_adaptive_11r;
321 
322 	/* If adaptive 11r is enabled set the FT AKM for AP */
323 	if (is_adaptive_11r)
324 		scm_check_and_update_adaptive_11r_key_mgmt_support(ap_crypto);
325 
326 	scm_debug("ap_crypto->key_mgmt:%d, filter->key_mgmt:%d",
327 		  ap_crypto->key_mgmt, filter->key_mgmt);
328 	match = scm_chk_crypto_params(filter, ap_crypto, is_adaptive_11r,
329 				      db_entry, security);
330 	qdf_mem_free(ap_crypto);
331 
332 	return match;
333 }
334 
335 /**
336  * scm_check_wpa() - Check if scan entry support WPA security
337  * @filter: scan filter
338  * @db_entry: db entry
339  * @security: matched security.
340  *
341  * Return: true if WPA security else false
342  */
343 static bool scm_check_wpa(struct scan_filter *filter,
344 			  struct scan_cache_entry *db_entry,
345 			  struct security_info *security)
346 {
347 	QDF_STATUS status;
348 	struct wlan_crypto_params *ap_crypto;
349 	bool match;
350 
351 	if (!util_scan_entry_wpa(db_entry)) {
352 		scm_debug(QDF_MAC_ADDR_FMT" : doesn't have WPA IE",
353 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
354 		return false;
355 	}
356 
357 	ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto));
358 	if (!ap_crypto)
359 		return false;
360 
361 	status = wlan_crypto_wpaie_check(ap_crypto,
362 					 util_scan_entry_wpa(db_entry));
363 	if (QDF_IS_STATUS_ERROR(status)) {
364 		scm_err(QDF_MAC_ADDR_FMT": failed to parse WPA IE, status %d",
365 			QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status);
366 		qdf_mem_free(ap_crypto);
367 		return false;
368 	}
369 
370 	match = scm_chk_crypto_params(filter, ap_crypto, false,
371 				      db_entry, security);
372 	qdf_mem_free(ap_crypto);
373 
374 	return match;
375 }
376 
377 /**
378  * scm_check_wapi() - Check if scan entry support WAPI security
379  * @filter: scan filter
380  * @db_entry: db entry
381  * @security: matched security.
382  *
383  * Return: true if WAPI security else false
384  */
385 static bool scm_check_wapi(struct scan_filter *filter,
386 			   struct scan_cache_entry *db_entry,
387 			   struct security_info *security)
388 {
389 	QDF_STATUS status;
390 	struct wlan_crypto_params *ap_crypto;
391 
392 	if (!util_scan_entry_wapi(db_entry)) {
393 		scm_debug(QDF_MAC_ADDR_FMT" : doesn't have WAPI IE",
394 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
395 		return false;
396 	}
397 
398 	ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto));
399 	if (!ap_crypto)
400 		return false;
401 
402 	status = wlan_crypto_wapiie_check(ap_crypto,
403 					  util_scan_entry_wapi(db_entry));
404 	if (QDF_IS_STATUS_ERROR(status)) {
405 		scm_err(QDF_MAC_ADDR_FMT": failed to parse WAPI IE, status %d",
406 			QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status);
407 		qdf_mem_free(ap_crypto);
408 		return false;
409 	}
410 
411 	if (!scm_chk_if_cipher_n_akm_match(filter, ap_crypto)) {
412 		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",
413 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes), filter->key_mgmt,
414 			  filter->mcastcipherset, filter->ucastcipherset,
415 			  filter->mgmtcipherset, filter->pmf_cap,
416 			  ap_crypto->key_mgmt, ap_crypto->mcastcipherset,
417 			  ap_crypto->ucastcipherset, ap_crypto->mgmtcipherset,
418 			  ap_crypto->rsn_caps);
419 		qdf_mem_free(ap_crypto);
420 
421 		return false;
422 	}
423 
424 	security->mcastcipherset =
425 		ap_crypto->mcastcipherset & filter->mcastcipherset;
426 	security->ucastcipherset =
427 		ap_crypto->ucastcipherset & filter->ucastcipherset;
428 	security->key_mgmt = ap_crypto->key_mgmt & filter->key_mgmt;
429 	security->rsn_caps = ap_crypto->rsn_caps;
430 	qdf_mem_free(ap_crypto);
431 
432 	return true;
433 }
434 
435 /**
436  * scm_match_any_security() - Check if any security in filter match
437  * @filter: scan filter
438  * @db_entry: db entry
439  * @security: matched security.
440  *
441  * Return: true if any security else false
442  */
443 static bool scm_match_any_security(struct scan_filter *filter,
444 				   struct scan_cache_entry *db_entry,
445 				   struct security_info *security)
446 {
447 	struct wlan_crypto_params *ap_crypto = {0};
448 	QDF_STATUS status;
449 	bool match = false;
450 
451 	ap_crypto = qdf_mem_malloc(sizeof(*ap_crypto));
452 	if (!ap_crypto)
453 		return match;
454 
455 	if (util_scan_entry_rsn(db_entry)) {
456 		status = wlan_crypto_rsnie_check(ap_crypto,
457 						 util_scan_entry_rsn(db_entry));
458 		if (QDF_IS_STATUS_ERROR(status)) {
459 			scm_err(QDF_MAC_ADDR_FMT": failed to parse RSN IE, status %d",
460 				QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status);
461 			goto free;
462 		}
463 		security->mcastcipherset = ap_crypto->mcastcipherset;
464 		security->ucastcipherset = ap_crypto->ucastcipherset;
465 		security->key_mgmt = ap_crypto->key_mgmt;
466 		security->rsn_caps = ap_crypto->rsn_caps;
467 		QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_RSNA);
468 		match = true;
469 		goto free;
470 	}
471 
472 	if (util_scan_entry_wpa(db_entry)) {
473 		status = wlan_crypto_wpaie_check(ap_crypto,
474 						 util_scan_entry_wpa(db_entry));
475 		if (QDF_IS_STATUS_ERROR(status)) {
476 			scm_err(QDF_MAC_ADDR_FMT": failed to parse WPA IE, status %d",
477 				QDF_MAC_ADDR_REF(db_entry->bssid.bytes), status);
478 			goto free;
479 		}
480 		security->mcastcipherset = ap_crypto->mcastcipherset;
481 		security->ucastcipherset = ap_crypto->ucastcipherset;
482 		security->key_mgmt = ap_crypto->key_mgmt;
483 		security->rsn_caps = ap_crypto->rsn_caps;
484 		QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_WPA);
485 		match = true;
486 		goto free;
487 	}
488 
489 	if (util_scan_entry_wapi(db_entry)) {
490 		status = wlan_crypto_wapiie_check(ap_crypto,
491 						util_scan_entry_wapi(db_entry));
492 		if (QDF_IS_STATUS_ERROR(status)) {
493 			scm_err(QDF_MAC_ADDR_FMT": failed to parse WPA IE, status %d",
494 				QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
495 				status);
496 			goto free;
497 		}
498 		security->mcastcipherset = ap_crypto->mcastcipherset;
499 		security->ucastcipherset = ap_crypto->ucastcipherset;
500 		security->key_mgmt = ap_crypto->key_mgmt;
501 		security->rsn_caps = ap_crypto->rsn_caps;
502 		QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_WAPI);
503 		match = true;
504 		goto free;
505 	}
506 
507 	if (db_entry->cap_info.wlan_caps.privacy) {
508 		QDF_SET_PARAM(security->ucastcipherset, WLAN_CRYPTO_CIPHER_WEP);
509 		QDF_SET_PARAM(security->mcastcipherset, WLAN_CRYPTO_CIPHER_WEP);
510 		QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_SHARED);
511 		match = true;
512 		goto free;
513 	}
514 
515 	QDF_SET_PARAM(security->ucastcipherset, WLAN_CRYPTO_CIPHER_NONE);
516 	QDF_SET_PARAM(security->mcastcipherset, WLAN_CRYPTO_CIPHER_NONE);
517 	QDF_SET_PARAM(security->authmodeset, WLAN_CRYPTO_AUTH_OPEN);
518 	match = true;
519 
520 free:
521 	qdf_mem_free(ap_crypto);
522 
523 	return match;
524 }
525 
526 /**
527  * scm_is_security_match() - Check if security in filter match
528  * @filter: scan filter
529  * @db_entry: db entry
530  * @security: matched security.
531  *
532  * Return: true if security match else false
533  */
534 static bool scm_is_security_match(struct scan_filter *filter,
535 				  struct scan_cache_entry *db_entry,
536 				  struct security_info *security)
537 {
538 	int i;
539 	bool match = false;
540 
541 	if (!filter->authmodeset)
542 		return scm_match_any_security(filter, db_entry, security);
543 
544 	for (i = 0; i < WLAN_CRYPTO_AUTH_MAX && !match; i++) {
545 		if (!QDF_HAS_PARAM(filter->authmodeset, i))
546 			continue;
547 
548 		security->authmodeset = 0;
549 		QDF_SET_PARAM(security->authmodeset, i);
550 
551 		switch (i) {
552 		case WLAN_CRYPTO_AUTH_NONE:
553 		case WLAN_CRYPTO_AUTH_OPEN:
554 		case WLAN_CRYPTO_AUTH_AUTO:
555 			match = scm_check_open(filter, db_entry, security);
556 			if (match)
557 				break;
558 		/* If not OPEN, then check WEP match */
559 			fallthrough;
560 		case WLAN_CRYPTO_AUTH_SHARED:
561 			match = scm_check_wep(filter, db_entry, security);
562 			break;
563 		case WLAN_CRYPTO_AUTH_8021X:
564 		case WLAN_CRYPTO_AUTH_RSNA:
565 		case WLAN_CRYPTO_AUTH_CCKM:
566 		case WLAN_CRYPTO_AUTH_SAE:
567 		case WLAN_CRYPTO_AUTH_FILS_SK:
568 			/* First check if there is a RSN match */
569 			match = scm_check_rsn(filter, db_entry, security);
570 			break;
571 		case WLAN_CRYPTO_AUTH_WPA:
572 			match = scm_check_wpa(filter, db_entry, security);
573 			break;
574 		case WLAN_CRYPTO_AUTH_WAPI:/* WAPI */
575 			match = scm_check_wapi(filter, db_entry, security);
576 			break;
577 		default:
578 			break;
579 		}
580 	}
581 
582 	return match;
583 }
584 
585 static bool scm_ignore_ssid_check_for_owe(struct scan_filter *filter,
586 					  struct scan_cache_entry *db_entry)
587 {
588 	bool is_hidden;
589 
590 	is_hidden = util_scan_entry_is_hidden_ap(db_entry);
591 	if (is_hidden &&
592 	    QDF_HAS_PARAM(filter->key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE) &&
593 	    util_is_bssid_match(&filter->bssid_hint, &db_entry->bssid))
594 		return true;
595 
596 	/* Dump only for hidden SSID as non-hidden are anyway rejected */
597 	if (is_hidden)
598 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore hidden AP as key_mgmt 0x%x is not OWE or bssid hint: "
599 			  QDF_MAC_ADDR_FMT " does not match",
600 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
601 			  filter->key_mgmt,
602 			  QDF_MAC_ADDR_REF(filter->bssid_hint.bytes));
603 	return false;
604 }
605 
606 #ifdef WLAN_FEATURE_FILS_SK
607 /**
608  * scm_is_fils_config_match() - Check if FILS config matches
609  * @filter: scan filter
610  * @db_entry: db entry
611  *
612  * Return: true if FILS config matches else false
613  */
614 static bool scm_is_fils_config_match(struct scan_filter *filter,
615 				     struct scan_cache_entry *db_entry)
616 {
617 	int i;
618 	struct fils_indication_ie *indication_ie;
619 	uint8_t *data;
620 	uint8_t *end_ptr;
621 
622 	if (!filter->fils_scan_filter.realm_check)
623 		return true;
624 
625 	if (!db_entry->ie_list.fils_indication)
626 		return false;
627 
628 	indication_ie =
629 		(struct fils_indication_ie *)db_entry->ie_list.fils_indication;
630 
631 	end_ptr = (uint8_t *)indication_ie + indication_ie->len + 2;
632 	data = indication_ie->variable_data;
633 
634 	if (indication_ie->is_cache_id_present &&
635 	    (data + CACHE_IDENTIFIER_LEN) <= end_ptr)
636 		data += CACHE_IDENTIFIER_LEN;
637 
638 	if (indication_ie->is_hessid_present &&
639 	    (data + HESSID_LEN) <= end_ptr)
640 		data += HESSID_LEN;
641 
642 	for (i = 1; i <= indication_ie->realm_identifiers_cnt &&
643 	     (data + REALM_HASH_LEN) <= end_ptr; i++) {
644 		if (!qdf_mem_cmp(filter->fils_scan_filter.fils_realm,
645 				 data, REALM_HASH_LEN))
646 			return true;
647 		/* Max realm count reached */
648 		if (indication_ie->realm_identifiers_cnt == i)
649 			break;
650 
651 		data = data + REALM_HASH_LEN;
652 	}
653 
654 	return false;
655 }
656 
657 #else
658 
659 static inline bool scm_is_fils_config_match(struct scan_filter *filter,
660 					    struct scan_cache_entry *db_entry)
661 {
662 	return true;
663 }
664 #endif
665 
666 static bool scm_check_dot11mode(struct scan_cache_entry *db_entry,
667 				struct scan_filter *filter)
668 {
669 	switch (filter->dot11mode) {
670 	case ALLOW_ALL:
671 		break;
672 	case ALLOW_11N_ONLY:
673 		if (!util_scan_entry_htcap(db_entry))
674 			return false;
675 		break;
676 	case ALLOW_11AC_ONLY:
677 		if (!util_scan_entry_vhtcap(db_entry))
678 			return false;
679 		break;
680 	case ALLOW_11AX_ONLY:
681 		if (!util_scan_entry_hecap(db_entry))
682 			return false;
683 		break;
684 	default:
685 		scm_debug("Invalid dot11mode filter passed %d",
686 			  filter->dot11mode);
687 	}
688 
689 	return true;
690 }
691 
692 #ifdef WLAN_FEATURE_11BE_MLO
693 static bool util_mlo_filter_match(struct wlan_objmgr_pdev *pdev,
694 				  struct scan_filter *filter,
695 				  struct scan_cache_entry *db_entry)
696 {
697 	uint8_t i, band_bitmap, assoc_band_bitmap;
698 	enum reg_wifi_band band;
699 	struct partner_link_info *partner_link;
700 	bool is_disabled;
701 
702 	if (!db_entry->ie_list.multi_link)
703 		return true;
704 	if (!filter->band_bitmap)
705 		return true;
706 
707 	/* Apply assoc band filter only for assoc link */
708 	band_bitmap = filter->band_bitmap & 0xf;
709 	assoc_band_bitmap = (filter->band_bitmap & 0xf0) >> 4;
710 	band = wlan_reg_freq_to_band(db_entry->channel.chan_freq);
711 	if ((assoc_band_bitmap && !(band_bitmap & BIT(band) & assoc_band_bitmap)) ||
712 	    (!assoc_band_bitmap && !(band_bitmap & BIT(band)))) {
713 		scm_debug("bss freq %d not match band bitmap: 0x%x",
714 			  db_entry->channel.chan_freq,
715 			  filter->band_bitmap);
716 		return false;
717 	}
718 	for (i = 0; i < db_entry->ml_info.num_links; i++) {
719 		partner_link = &db_entry->ml_info.link_info[i];
720 		band = wlan_reg_freq_to_band(partner_link->freq);
721 
722 		is_disabled = wlan_reg_is_disable_for_pwrmode(
723 				    pdev,
724 				    partner_link->freq,
725 				    REG_BEST_PWR_MODE);
726 		if (is_disabled) {
727 			scm_debug("partner link id %d freq %d disabled : "QDF_MAC_ADDR_FMT,
728 				  partner_link->link_id,
729 				  partner_link->freq,
730 				  QDF_MAC_ADDR_REF(
731 				  partner_link->link_addr.bytes));
732 			continue;
733 		}
734 		if (band_bitmap & BIT(band)) {
735 			scm_debug("partner link id %d freq %d match band bitmap: 0x%x "QDF_MAC_ADDR_FMT,
736 				  partner_link->link_id,
737 				  partner_link->freq,
738 				  filter->band_bitmap,
739 				  QDF_MAC_ADDR_REF(
740 				  partner_link->link_addr.bytes));
741 			partner_link->is_valid_link = true;
742 		}
743 	}
744 
745 	return true;
746 }
747 #else
748 static bool util_mlo_filter_match(struct wlan_objmgr_pdev *pdev,
749 				  struct scan_filter *filter,
750 				  struct scan_cache_entry *db_entry)
751 {
752 	return true;
753 }
754 #endif
755 
756 #ifdef WLAN_FEATURE_11BE
757 static bool util_eht_puncture_valid(struct scan_cache_entry *db_entry)
758 {
759 	struct wlan_ie_ehtops *eht_ops;
760 	int8_t orig_width;
761 	enum phy_ch_width width;
762 	qdf_freq_t center_freq_320m;
763 	uint16_t orig_puncture_bitmap;
764 	uint16_t new_puncture_bitmap = 0;
765 	QDF_STATUS status;
766 
767 	eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(db_entry);
768 	if (!eht_ops)
769 		return true;
770 	if (!QDF_GET_BITS(eht_ops->ehtop_param,
771 			  EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS))
772 		return true;
773 	orig_puncture_bitmap = db_entry->channel.puncture_bitmap;
774 	if (!orig_puncture_bitmap)
775 		return true;
776 
777 	orig_width = QDF_GET_BITS(eht_ops->control,
778 				  EHTOP_INFO_CHAN_WIDTH_IDX,
779 				  EHTOP_INFO_CHAN_WIDTH_BITS);
780 	if (orig_width == WLAN_EHT_CHWIDTH_320) {
781 		width = CH_WIDTH_320MHZ;
782 		center_freq_320m = db_entry->channel.cfreq1;
783 	} else {
784 		width = orig_width;
785 		center_freq_320m = 0;
786 	}
787 
788 	status = wlan_reg_extract_puncture_by_bw(width,
789 						 orig_puncture_bitmap,
790 						 db_entry->channel.chan_freq,
791 						 center_freq_320m,
792 						 CH_WIDTH_20MHZ,
793 						 &new_puncture_bitmap);
794 	if (QDF_IS_STATUS_ERROR(status) || new_puncture_bitmap) {
795 		scm_debug(QDF_MAC_ADDR_FMT "freq %d width %d 320m center %d puncture: orig %d new %d status %d",
796 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
797 			  db_entry->channel.chan_freq, width, center_freq_320m,
798 			  orig_puncture_bitmap, new_puncture_bitmap, status);
799 		return false;
800 	} else {
801 		return true;
802 	}
803 }
804 #else
805 static bool util_eht_puncture_valid(struct scan_cache_entry *db_entry)
806 {
807 	return true;
808 }
809 #endif
810 
811 bool scm_filter_match(struct wlan_objmgr_psoc *psoc,
812 		      struct scan_cache_entry *db_entry,
813 		      struct scan_filter *filter,
814 		      struct security_info *security)
815 {
816 	int i;
817 	bool match = false;
818 	struct scan_default_params *def_param;
819 	struct wlan_objmgr_pdev *pdev;
820 
821 	def_param = wlan_scan_psoc_get_def_params(psoc);
822 	if (!def_param)
823 		return false;
824 
825 	if (db_entry->ssid.length) {
826 		for (i = 0; i < filter->num_of_ssid; i++) {
827 			if (util_is_ssid_match(&filter->ssid_list[i],
828 			   &db_entry->ssid)) {
829 				match = true;
830 				break;
831 			}
832 		}
833 	}
834 	/*
835 	 * In OWE transition mode, ssid is hidden. And supplicant does not issue
836 	 * scan with specific ssid prior to connect as in other hidden ssid
837 	 * cases. Add explicit check to allow OWE when ssid is hidden.
838 	 */
839 	if (!match)
840 		match = scm_ignore_ssid_check_for_owe(filter, db_entry);
841 
842 	if (!match && filter->num_of_ssid)
843 		return false;
844 
845 	match = false;
846 	for (i = 0; i < filter->num_of_bssid; i++) {
847 		if (util_is_bssid_match(&filter->bssid_list[i],
848 		   &db_entry->bssid)) {
849 			match = true;
850 			break;
851 		}
852 	}
853 
854 	if (!match && filter->num_of_bssid) {
855 		/*
856 		 * Do not print if ssid is not present in filter to avoid
857 		 * excessive prints
858 		 */
859 		if (filter->num_of_ssid)
860 			scm_debug(QDF_MAC_ADDR_FMT ": Ignore as BSSID not in list (no. of BSSID in list %d)",
861 				  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
862 				  filter->num_of_bssid);
863 		return false;
864 	}
865 
866 	if (filter->age_threshold &&
867 	    filter->age_threshold < util_scan_entry_age(db_entry)) {
868 		/*
869 		 * Do not print if bssid/ssid is not present in filter to avoid
870 		 * excessive prints
871 		 */
872 		if (filter->num_of_bssid || filter->num_of_ssid)
873 			scm_debug(QDF_MAC_ADDR_FMT ": Ignore as age %lu ms is greater than threshold %lu ms",
874 				  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
875 				  util_scan_entry_age(db_entry),
876 				  filter->age_threshold);
877 		return false;
878 	}
879 
880 	if (filter->dot11mode && !scm_check_dot11mode(db_entry, filter)) {
881 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as dot11mode %d didn't match phymode %d",
882 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
883 			  filter->dot11mode, db_entry->phy_mode);
884 		return false;
885 	}
886 
887 	if (filter->ignore_6ghz_channel &&
888 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(db_entry->channel.chan_freq)) {
889 		/*
890 		 * Do not print if bssid/ssid is not present in filter to avoid
891 		 * excessive prints
892 		 */
893 		if (filter->num_of_bssid || filter->num_of_ssid)
894 			scm_debug(QDF_MAC_ADDR_FMT ": Ignore as its on 6Ghz freq %d",
895 				  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
896 				  db_entry->channel.chan_freq);
897 
898 		return false;
899 	}
900 
901 	pdev = wlan_objmgr_get_pdev_by_id(psoc, db_entry->pdev_id,
902 					  WLAN_SCAN_ID);
903 	if (!pdev) {
904 		scm_err(QDF_MAC_ADDR_FMT ": Ignore as pdev not found",
905 			QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
906 		return false;
907 	}
908 
909 	if (filter->ignore_nol_chan &&
910 	    utils_dfs_is_freq_in_nol(pdev, db_entry->channel.chan_freq)) {
911 		wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID);
912 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as chan in NOL list",
913 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
914 		return false;
915 	}
916 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID);
917 
918 	match = false;
919 	for (i = 0; i < filter->num_of_channels; i++) {
920 		if (!filter->chan_freq_list[i] ||
921 		    filter->chan_freq_list[i] ==
922 		    db_entry->channel.chan_freq) {
923 			match = true;
924 			break;
925 		}
926 	}
927 
928 	if (!match && filter->num_of_channels) {
929 		/*
930 		 * Do not print if bssid/ssid is not present in filter to avoid
931 		 * excessive prints (e.g RRM case where only freq list is
932 		 * provided to get AP's in specific frequencies)
933 		 */
934 		if (filter->num_of_bssid || filter->num_of_ssid)
935 			scm_debug(QDF_MAC_ADDR_FMT ": Ignore as AP's freq %d is not in freq list",
936 				  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
937 				  db_entry->channel.chan_freq);
938 		return false;
939 	}
940 
941 	if (filter->rrm_measurement_filter)
942 		return true;
943 
944 	if (!filter->ignore_auth_enc_type && !filter->match_security_func &&
945 	    !scm_is_security_match(filter, db_entry, security)) {
946 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as security profile didn't match",
947 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
948 		return false;
949 	}
950 
951 	if (filter->match_security_func &&
952 	    !filter->match_security_func(filter->match_security_func_arg,
953 					 db_entry)) {
954 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as custom security match failed",
955 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
956 		return false;
957 	}
958 
959 	if (filter->ccx_validate_bss &&
960 	    !filter->ccx_validate_bss(filter->ccx_validate_bss_arg,
961 				      db_entry, 0)) {
962 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as CCX validateion failed",
963 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
964 		return false;
965 	}
966 
967 	if (!util_is_bss_type_match(filter->bss_type, db_entry->cap_info)) {
968 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as bss type didn't match cap_info %x bss_type %d",
969 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes),
970 			  db_entry->cap_info.value, filter->bss_type);
971 		return false;
972 	}
973 
974 	/* Match realm */
975 	if (!scm_is_fils_config_match(filter, db_entry)) {
976 		scm_debug(QDF_MAC_ADDR_FMT ":Ignore as fils config didn't match",
977 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
978 		return false;
979 	}
980 
981 	if (!util_mdie_match(filter->mobility_domain,
982 	   (struct rsn_mdie *)db_entry->ie_list.mdie)) {
983 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as mdie didn't match",
984 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
985 		return false;
986 	}
987 
988 	if (!util_mlo_filter_match(pdev, filter, db_entry)) {
989 		scm_debug(QDF_MAC_ADDR_FMT ": Ignore as mlo filter didn't match",
990 			  QDF_MAC_ADDR_REF(db_entry->bssid.bytes));
991 		return false;
992 	}
993 
994 	if (!util_eht_puncture_valid(db_entry))
995 		return false;
996 
997 	return true;
998 }
999