diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h
index f72c39826ee7..49251a52c4b2 100644
--- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h
+++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -721,8 +721,8 @@ bool wlan_crypto_check_wpa_match(struct wlan_objmgr_psoc *psoc,
*
* Return: pointer to RSNXE capability or NULL
*/
-uint8_t *
-wlan_crypto_parse_rsnxe_ie(uint8_t *rsnxe_ie, uint8_t *cap_len);
+const uint8_t *
+wlan_crypto_parse_rsnxe_ie(const uint8_t *rsnxe_ie, uint8_t *cap_len);
/**
* wlan_get_crypto_params_from_wapi_ie - Function to get crypto params
diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h
index 6105341f303e..e42a1a65cf05 100644
--- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h
+++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h
@@ -233,6 +233,11 @@ enum wlan_crypto_key_type {
(_c == WLAN_CRYPTO_CIPHER_WEP_40) || \
(_c == WLAN_CRYPTO_CIPHER_WEP_104))
+#define DEFAULT_KEYMGMT_6G_MASK 0xFFFFFFFF
+
+/* AKM wlan_crypto_key_mgmt 0-8, 12-15 and 24 are not allowed. */
+#define ALLOWED_KEYMGMT_6G_MASK 0xFEFF0E00
+
/*
* enum fils_erp_cryptosuite: this enum defines the cryptosuites used
* to calculate auth tag and auth tag length as defined by RFC 6696 5.3.1
diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c
index 7a93d462adec..25b18d7e4f0a 100644
--- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c
+++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -4347,11 +4347,11 @@ wlan_crypto_reset_prarams(struct wlan_crypto_params *params)
params->rsn_caps = 0;
}
-uint8_t *
-wlan_crypto_parse_rsnxe_ie(uint8_t *rsnxe_ie, uint8_t *cap_len)
+const uint8_t *
+wlan_crypto_parse_rsnxe_ie(const uint8_t *rsnxe_ie, uint8_t *cap_len)
{
uint8_t len;
- uint8_t *ie;
+ const uint8_t *ie;
if (!rsnxe_ie)
return NULL;
diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c b/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c
index 23a0d84fcdfe..f997b91321e3 100644
--- a/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c
+++ b/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c
@@ -703,7 +703,8 @@ cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry *entry,
struct scoring_cfg *score_params,
bool *sae_pk_cap_present)
{
- uint8_t *rsnxe_ie, *rsnxe_cap, cap_len;
+ uint8_t *rsnxe_ie, cap_len;
+ const uint8_t *rsnxe_cap;
rsnxe_ie = util_scan_entry_rsnxe(entry);
@@ -1295,6 +1296,27 @@ cm_calculate_etp_score(struct wlan_objmgr_psoc *psoc,
entry->rssi_raw,
phy_config);
}
+
+#ifdef CONFIG_BAND_6GHZ
+static bool cm_check_h2e_support(const uint8_t *rsnxe, uint8_t sae_pwe)
+{
+ const uint8_t *rsnxe_cap;
+ uint8_t cap_len;
+
+ rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len);
+ if (!rsnxe_cap) {
+ mlme_debug("RSNXE caps not present");
+ return false;
+ }
+
+ if (*rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_SAE_H2E)
+ return true;
+
+ mlme_debug("RSNXE caps %x dont have H2E support", *rsnxe_cap);
+
+ return false;
+}
+#endif
#else
static bool
cm_get_pcl_weight_of_channel(uint32_t chan_freq,
@@ -1353,6 +1375,19 @@ cm_calculate_etp_score(struct wlan_objmgr_psoc *psoc,
{
return 0;
}
+
+#ifdef CONFIG_BAND_6GHZ
+static bool cm_check_h2e_support(const uint8_t *rsnxe, uint8_t sae_pwe)
+{
+ /* limiting to H2E usage only */
+ if (sae_pwe == 1)
+ return true;
+
+ mlme_debug("sae_pwe %d is not H2E", sae_pwe);
+
+ return false;
+}
+#endif
#endif
/**
@@ -1787,6 +1822,133 @@ void wlan_cm_calculate_bss_score(struct wlan_objmgr_pdev *pdev,
}
}
+#ifdef CONFIG_BAND_6GHZ
+bool wlan_cm_6ghz_allowed_for_akm(struct wlan_objmgr_psoc *psoc,
+ uint32_t key_mgmt, uint16_t rsn_caps,
+ const uint8_t *rsnxe, uint8_t sae_pwe,
+ bool is_wps)
+{
+ struct psoc_mlme_obj *mlme_psoc_obj;
+ struct scoring_cfg *config;
+
+ /* Allow connection for WPS security */
+ if (is_wps)
+ return true;
+
+ mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+ if (!mlme_psoc_obj)
+ return false;
+
+ config = &mlme_psoc_obj->psoc_cfg.score_config;
+ /*
+ * if check_6ghz_security is not set check if key_mgmt_mask_6ghz is set
+ * if key_mgmt_mask_6ghz is set check if AKM matches the user configured
+ * 6Ghz security
+ */
+ if (!config->check_6ghz_security) {
+ if (!config->key_mgmt_mask_6ghz)
+ return true;
+ /* Check if AKM is allowed as per user 6Ghz allowed AKM mask */
+ if ((config->key_mgmt_mask_6ghz & key_mgmt) != key_mgmt) {
+ mlme_debug("usr configured mask %x didn't match AKM %x",
+ config->key_mgmt_mask_6ghz, key_mgmt);
+ return false;
+ }
+
+ return true;
+ }
+
+ /* Check if the AKM is allowed as per the 6Ghz allowed AKM mask */
+ if ((key_mgmt & ALLOWED_KEYMGMT_6G_MASK) != key_mgmt)
+ return false;
+
+ /* if check_6ghz_security is set validate all checks for 6Ghz */
+ if (!(rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED))
+ return false;
+
+ /* for SAE we need to check H2E support */
+ if (!(QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
+ QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE)))
+ return true;
+
+ return cm_check_h2e_support(rsnxe, sae_pwe);
+}
+
+void wlan_cm_set_check_6ghz_security(struct wlan_objmgr_psoc *psoc,
+ bool value)
+{
+ struct psoc_mlme_obj *mlme_psoc_obj;
+
+ mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+ if (!mlme_psoc_obj)
+ return;
+
+ mlme_debug("6ghz security check val %x", value);
+ mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security = value;
+}
+
+void wlan_cm_reset_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
+{
+ struct psoc_mlme_obj *mlme_psoc_obj;
+
+ mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+ if (!mlme_psoc_obj)
+ return;
+
+ mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security =
+ cfg_get(psoc, CFG_CHECK_6GHZ_SECURITY);
+}
+
+bool wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
+{
+ struct psoc_mlme_obj *mlme_psoc_obj;
+
+ mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+ if (!mlme_psoc_obj)
+ return false;
+
+ return mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security;
+}
+
+void wlan_cm_set_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc,
+ uint32_t value)
+{
+ struct psoc_mlme_obj *mlme_psoc_obj;
+
+ mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+ if (!mlme_psoc_obj)
+ return;
+
+ mlme_debug("key_mgmt_mask_6ghz %x", value);
+ mlme_psoc_obj->psoc_cfg.score_config.key_mgmt_mask_6ghz = value;
+}
+
+uint32_t wlan_cm_get_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc)
+{
+ struct psoc_mlme_obj *mlme_psoc_obj;
+
+ mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+ if (!mlme_psoc_obj)
+ return DEFAULT_KEYMGMT_6G_MASK;
+
+ return mlme_psoc_obj->psoc_cfg.score_config.key_mgmt_mask_6ghz;
+}
+
+static void cm_fill_6ghz_params(struct wlan_objmgr_psoc *psoc,
+ struct scoring_cfg *score_cfg)
+{
+ /* Allow all security in 6Ghz by default */
+ score_cfg->check_6ghz_security = cfg_get(psoc, CFG_CHECK_6GHZ_SECURITY);
+ score_cfg->key_mgmt_mask_6ghz =
+ cfg_get(psoc, CFG_6GHZ_ALLOWED_AKM_MASK);
+}
+#else
+static inline void cm_fill_6ghz_params(struct wlan_objmgr_psoc *psoc,
+ struct scoring_cfg *score_cfg)
+{
+}
+#endif
+
static uint32_t
cm_limit_max_per_index_score(uint32_t per_index_score)
{
@@ -1949,4 +2111,5 @@ void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc,
score_cfg->vendor_roam_score_algorithm =
cfg_get(psoc, CFG_VENDOR_ROAM_SCORE_ALGORITHM);
score_cfg->check_assoc_disallowed = true;
+ cm_fill_6ghz_params(psoc, score_cfg);
}
diff --git a/umac/mlme/connection_mgr/dispatcher/inc/cfg_mlme_score_params.h b/umac/mlme/connection_mgr/dispatcher/inc/cfg_mlme_score_params.h
index 85e845afd65b..44cc92f4eeb0 100644
--- a/umac/mlme/connection_mgr/dispatcher/inc/cfg_mlme_score_params.h
+++ b/umac/mlme/connection_mgr/dispatcher/inc/cfg_mlme_score_params.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -1104,6 +1104,62 @@
CFG_INI_BOOL("vendor_roam_score_algorithm", false, \
"Roam candidate selection score algorithm")
+#ifdef CONFIG_BAND_6GHZ
+/*
+ *
+ * check_6ghz_security - Enable check for 6Ghz allowed security
+ * BSSID.
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to Enable check for 6Ghz allowed security. If enabled
+ * only WPA3 and other allowed security will be allowed for 6Ghz connection
+ *
+ * Related: None
+ *
+ * Supported Feature: STA
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_CHECK_6GHZ_SECURITY CFG_INI_BOOL(\
+ "check_6ghz_security", 0, \
+ "Enable check for 6Ghz allowed security")
+/*
+ *
+ * key_mgmt_mask_6ghz - AKM bit mask (@wlan_crypto_key_mgmt) allowed in 6Ghz
+ * channel
+ * @Min: 0
+ * @Max: 0xffffffff
+ * @Default: 0xffffffff
+ *
+ * This ini is used to set allowed AKM check for 6Ghz. If enabled
+ * only only AKM bits allowed will be used to connect to candidate.
+ * valid only if check_6ghz_security is 0. By default all AKM are allowed
+ *
+ * Related: check_6Ghz_security
+ *
+ * Supported Feature: STA
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_6GHZ_ALLOWED_AKM_MASK CFG_INI_UINT(\
+ "key_mgmt_mask_6ghz",\
+ 0, DEFAULT_KEYMGMT_6G_MASK, DEFAULT_KEYMGMT_6G_MASK,\
+ CFG_VALUE_OR_DEFAULT, \
+ "Set priority for connection with bssid_hint")
+
+#define CFG_6GHZ_CONFIG \
+ CFG(CFG_CHECK_6GHZ_SECURITY) \
+ CFG(CFG_6GHZ_ALLOWED_AKM_MASK)
+#else
+#define CFG_6GHZ_CONFIG
+#endif
+
#define CFG_MLME_SCORE_ALL \
CFG(CFG_SCORING_RSSI_WEIGHTAGE) \
CFG(CFG_SCORING_HT_CAPS_WEIGHTAGE) \
@@ -1141,6 +1197,7 @@
CFG(CFG_SCORING_OCE_WAN_SCORE_IDX_11_TO_8) \
CFG(CFG_SCORING_OCE_WAN_SCORE_IDX_15_TO_12) \
CFG(CFG_IS_BSSID_HINT_PRIORITY) \
- CFG(CFG_VENDOR_ROAM_SCORE_ALGORITHM)
+ CFG(CFG_VENDOR_ROAM_SCORE_ALGORITHM) \
+ CFG_6GHZ_CONFIG
#endif /* __CFG_MLME_SCORE_PARAMS_H */
diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_bss_score_param.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_bss_score_param.h
index 8e6c3a791b67..75d53a564b4e 100644
--- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_bss_score_param.h
+++ b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_bss_score_param.h
@@ -128,6 +128,8 @@ struct per_slot_score {
* @is_bssid_hint_priority: True if bssid_hint is given priority
* @check_assoc_disallowed: Should assoc be disallowed if MBO OCE IE indicate so
* @vendor_roam_score_algorithm: Preferred ETP vendor roam score algorithm
+ * @check_6ghz_security: check security for 6Ghz candidate
+ * @key_mgmt_mask_6ghz: user configurable mask for 6ghz AKM
*/
struct scoring_cfg {
struct weight_cfg weight_config;
@@ -140,6 +142,8 @@ struct scoring_cfg {
bool is_bssid_hint_priority;
bool check_assoc_disallowed;
bool vendor_roam_score_algorithm;
+ uint8_t check_6ghz_security;
+ uint32_t key_mgmt_mask_6ghz;
};
/**
@@ -225,6 +229,102 @@ void wlan_cm_calculate_bss_score(struct wlan_objmgr_pdev *pdev,
void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc,
struct scoring_cfg *score_cfg);
+/**
+ * wlan_cm_6ghz_allowed_for_akm() - check if 6Ghz channel can be allowed for AKM
+ * @psoc: pointer to psoc object
+ * @key_mgmt: key mgmt used
+ * @rsn_caps: rsn caps
+ * @rsnxe: rsnxe pointer if present
+ * @sae_pwe: support for SAE password
+ * @is_wps: if security is WPS
+ *
+ * Return: bool
+ */
+#ifdef CONFIG_BAND_6GHZ
+bool wlan_cm_6ghz_allowed_for_akm(struct wlan_objmgr_psoc *psoc,
+ uint32_t key_mgmt, uint16_t rsn_caps,
+ const uint8_t *rsnxe, uint8_t sae_pwe,
+ bool is_wps);
+
+/**
+ * wlan_cm_set_check_6ghz_security() - Set check 6Ghz security
+ * @psoc: pointer to psoc object
+ * @value: value to be set
+ *
+ * Return: void
+ */
+void wlan_cm_set_check_6ghz_security(struct wlan_objmgr_psoc *psoc,
+ bool value);
+
+/**
+ * wlan_cm_reset_check_6ghz_security() - reset check 6Ghz security to orignal
+ * value
+ * @psoc: pointer to psoc object
+ *
+ * Return: void
+ */
+void wlan_cm_reset_check_6ghz_security(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_cm_get_check_6ghz_security() - Get 6Ghz allowe AKM mask
+ * @psoc: pointer to psoc object
+ * @value: value to be set
+ *
+ * Return: value
+ */
+bool wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_cm_set_6ghz_key_mgmt_mask() - Set 6Ghz allowe AKM mask
+ * @psoc: pointer to psoc object
+ *
+ * Return: void
+ */
+void wlan_cm_set_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc,
+ uint32_t value);
+
+/**
+ * wlan_cm_get_6ghz_key_mgmt_mask() - Get 6Ghz allowe AKM mask
+ * @psoc: pointer to psoc object
+ *
+ * Return: value
+ */
+uint32_t wlan_cm_get_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc);
+
+#else
+static inline bool
+wlan_cm_6ghz_allowed_for_akm(struct wlan_objmgr_psoc *psoc,
+ uint32_t key_mgmt, uint16_t rsn_caps,
+ const uint8_t *rsnxe, uint8_t sae_pwe,
+ bool is_wps)
+{
+ return true;
+}
+
+static inline
+void wlan_cm_set_check_6ghz_security(struct wlan_objmgr_psoc *psoc,
+ bool value) {}
+
+static inline
+void wlan_cm_reset_check_6ghz_security(struct wlan_objmgr_psoc *psoc) {}
+
+static inline
+bool wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
+{
+ return false;
+}
+
+static inline
+void wlan_cm_set_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc,
+ uint32_t value) {}
+
+static inline
+uint32_t wlan_cm_get_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc)
+{
+ return DEFAULT_KEYMGMT_6G_MASK;
+}
+#endif
+
#ifdef CONN_MGR_ADV_FEATURE
/**
* wlan_cm_set_check_assoc_disallowed() - Set check assoc disallowed param
diff --git a/umac/scan/core/src/wlan_scan_cache_db.c b/umac/scan/core/src/wlan_scan_cache_db.c
index f9d5462f65c5..13ff41bfd5bb 100644
--- a/umac/scan/core/src/wlan_scan_cache_db.c
+++ b/umac/scan/core/src/wlan_scan_cache_db.c
@@ -52,6 +52,9 @@
#include "wlan_reg_ucfg_api.h"
#include
#include
+#include "wlan_crypto_global_def.h"
+#include "wlan_crypto_global_api.h"
+#include "wlan_cm_bss_score_param.h"
#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
@@ -915,6 +918,10 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn)
qdf_list_node_t *next_node = NULL;
struct scan_cache_node *scan_node;
struct wlan_frame_hdr *hdr = NULL;
+ struct wlan_crypto_params sec_params;
+ uint8_t sae_pwe = 0;
+ const uint8_t *rsnxe_cap;
+ uint8_t rsnxe_len = 0;
if (!bcn) {
scm_err("bcn is NULL");
@@ -1010,6 +1017,49 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn)
qdf_mem_free(scan_node);
continue;
}
+ if (wlan_cm_get_check_6ghz_security(psoc) &&
+ wlan_reg_is_6ghz_chan_freq(scan_entry->channel.chan_freq)) {
+ rsnxe_cap = wlan_crypto_parse_rsnxe_ie(
+ util_scan_entry_rsnxe(scan_entry),
+ &rsnxe_len);
+ if (!util_scan_entry_rsn(scan_entry) || !rsnxe_cap) {
+ scm_info("Drop frame from "QDF_MAC_ADDR_FMT
+ ": No RSN/RSNXE IE for 6GHz AP",
+ QDF_MAC_ADDR_REF(
+ scan_entry->bssid.bytes));
+ util_scan_free_cache_entry(scan_entry);
+ qdf_mem_free(scan_node);
+ continue;
+ }
+ status = wlan_crypto_rsnie_check(&sec_params,
+ util_scan_entry_rsn(scan_entry));
+ if (QDF_IS_STATUS_ERROR(status)) {
+ scm_info("Drop frame from 6GHz AP "
+ QDF_MAC_ADDR_FMT
+ ": RSN IE parse failed, status %d",
+ QDF_MAC_ADDR_REF(
+ scan_entry->bssid.bytes),
+ status);
+ util_scan_free_cache_entry(scan_entry);
+ qdf_mem_free(scan_node);
+ continue;
+ }
+ if (*rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_SAE_H2E)
+ sae_pwe = 1;
+ if (!wlan_cm_6ghz_allowed_for_akm(psoc,
+ sec_params.key_mgmt,
+ sec_params.rsn_caps,
+ util_scan_entry_rsnxe(scan_entry),
+ sae_pwe, false)) {
+ scm_err("Drop frame from "QDF_MAC_ADDR_FMT
+ ": Security check failed for 6GHz AP",
+ QDF_MAC_ADDR_REF(
+ scan_entry->bssid.bytes));
+ util_scan_free_cache_entry(scan_entry);
+ qdf_mem_free(scan_node);
+ continue;
+ }
+ }
if (scan_obj->cb.update_beacon)
scan_obj->cb.update_beacon(pdev, scan_entry);