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);