qcacmn: Drop the invalid 6GHz security beacon from scan result

Validate the 6GHz AP beacon in the scan result for valid security
if user enables the 6GHz security checks.
Drop the beacon from scan result if valid security is not found.

Change-Id: I6e02e77cc996b4f4fb7dc7a1678990419a51c79e
CRs-Fixed: 2904741
This commit is contained in:
Kiran Kumar Lokere 2021-03-18 14:46:54 -07:00 • committed by snandini
commit 89fb2883be
7 changed files with 385 additions and 10 deletions

View file

@ -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

View file

@ -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

View file

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

View file

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

View file

@ -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
/*
* <ini>
* 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
*
* </ini>
*/
#define CFG_CHECK_6GHZ_SECURITY CFG_INI_BOOL(\
"check_6ghz_security", 0, \
"Enable check for 6Ghz allowed security")
/*
* <ini>
* 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
*
* </ini>
*/
#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 */

View file

@ -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

View file

@ -52,6 +52,9 @@
#include "wlan_reg_ucfg_api.h"
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_dfs_utils_api.h>
#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);