From b5422c951fd9e752b1838b37be496575823a4e79 Mon Sep 17 00:00:00 2001 From: Surya Prakash Sivaraj Date: Mon, 29 Jan 2024 17:01:25 +0530 Subject: [PATCH 01/15] qcacmn: Fix potential OOB read in util_scan_parse_mbssid() If the length of the MBSSID IE is 0, then there is a potential OOB read in util_scan_parse_mbssid(), when the Max BSSID indicator field is accessed. To fix this, do not proceed with MBSSID parsing if the length of the MBSSID IE is zero. Change-Id: I2c7a7641b77fed20a910cb77035588a7540caa62 CRs-Fixed: 3717567 --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 8fac470063c3..e8b0b8ccb428 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2341,6 +2341,15 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, if (!mbssid_elem) break; + /* + * The max_bssid_indicator field is mandatory, therefore the + * length of the MBSSID element should atleast be 1. + */ + if (!mbssid_elem[TAG_LEN_POS]) { + scm_debug_rl("MBSSID IE is of length zero"); + break; + } + mbssid_info.profile_count = (1 << mbssid_elem[MBSSID_INDICATOR_POS]); From 39dddc6f4f0539c82777656eeeccf656faae831a Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Wed, 31 Jan 2024 16:15:05 +0530 Subject: [PATCH 02/15] qcacmn: Fix potential OOB read in util_scan_is_split_prof_found() If the tag length in next_elem is some invalid high value then the existing length check can still pass and lead to the OOB access. Add an OOB check w.r.t total IE length to ensure it has the minimum number of bytes in the buffer. Change-Id: I9778a3e0ced05d3246d91e23c2a47f7318634d75 CRs-Fixed: 3717566 --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index e8b0b8ccb428..730aa4bea0bb 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2272,6 +2272,9 @@ static bool util_scan_is_split_prof_found(uint8_t *next_elem, { uint8_t *next_mbssid_elem; + if ((next_elem + MIN_IE_LEN + VALID_ELEM_LEAST_LEN) > (ie + ielen)) + return false; + if (next_elem[0] == WLAN_ELEMID_MULTIPLE_BSSID) { if ((next_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) && (next_elem[SUBELEM_DATA_POS_FROM_MBSSID] != From 0b0c52f9e4e9a4ef64d6cb7ca0fa9041f875400b Mon Sep 17 00:00:00 2001 From: Surya Prakash Sivaraj Date: Mon, 29 Jan 2024 17:01:25 +0530 Subject: [PATCH 03/15] qcacmn: Fix potential OOB read in util_scan_parse_mbssid() If the length of the MBSSID IE is 0, then there is a potential OOB read in util_scan_parse_mbssid(), when the Max BSSID indicator field is accessed. To fix this, do not proceed with MBSSID parsing if the length of the MBSSID IE is zero. Change-Id: I2c7a7641b77fed20a910cb77035588a7540caa62 CRs-Fixed: 3717567 (cherry picked from commit b5422c951fd9e752b1838b37be496575823a4e79) --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 8fac470063c3..e8b0b8ccb428 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2341,6 +2341,15 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, if (!mbssid_elem) break; + /* + * The max_bssid_indicator field is mandatory, therefore the + * length of the MBSSID element should atleast be 1. + */ + if (!mbssid_elem[TAG_LEN_POS]) { + scm_debug_rl("MBSSID IE is of length zero"); + break; + } + mbssid_info.profile_count = (1 << mbssid_elem[MBSSID_INDICATOR_POS]); From 705a98b0e13768caf964e235a434b767ef138547 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Wed, 31 Jan 2024 16:15:05 +0530 Subject: [PATCH 04/15] qcacmn: Fix potential OOB read in util_scan_is_split_prof_found() If the tag length in next_elem is some invalid high value then the existing length check can still pass and lead to the OOB access. Add an OOB check w.r.t total IE length to ensure it has the minimum number of bytes in the buffer. Change-Id: I9778a3e0ced05d3246d91e23c2a47f7318634d75 CRs-Fixed: 3717566 (cherry picked from commit 39dddc6f4f0539c82777656eeeccf656faae831a) --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 8fac470063c3..007f98e86053 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2272,6 +2272,9 @@ static bool util_scan_is_split_prof_found(uint8_t *next_elem, { uint8_t *next_mbssid_elem; + if ((next_elem + MIN_IE_LEN + VALID_ELEM_LEAST_LEN) > (ie + ielen)) + return false; + if (next_elem[0] == WLAN_ELEMID_MULTIPLE_BSSID) { if ((next_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) && (next_elem[SUBELEM_DATA_POS_FROM_MBSSID] != From 05fbfac24f62e5c426c13022383397327c0510e2 Mon Sep 17 00:00:00 2001 From: Adwait Nayak Date: Sat, 2 Apr 2022 00:06:04 +0530 Subject: [PATCH 05/15] qcacmn: Fix memleak in MBSSIE handler For corrupt beacon frame, the memory allocated for split_prof_start is getting allocated for split profile case. But since there are no other nonTx profile or new MBSSID element present afterwards, Hence, added mem free to handle this scenario. Change-Id: I6b93ae0be97d72264071d1ce99345f8c0c23f81d CRs-Fixed: 3156909 --- .../scan/dispatcher/src/wlan_scan_utils_api.c | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 730aa4bea0bb..dc3791c1f1a6 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2399,8 +2399,10 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, subie_len, mbssid_info.split_prof_continue, mbssid_info.prof_residue); - if (mbssid_info.split_prof_continue) + if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); + split_prof_start = NULL; + } qdf_mem_free(new_ie); return QDF_STATUS_E_INVAL; @@ -2422,6 +2424,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, subelement[ID_POS], subelement[TAG_LEN_POS]); qdf_mem_free(split_prof_start); + split_prof_start = NULL; qdf_mem_free(new_ie); return QDF_STATUS_E_INVAL; } else if (retval == INVALID_NONTX_PROF) { @@ -2533,14 +2536,21 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, PAYLOAD_START_POS), subie_len, new_ie); - if (!new_ie_len) + if (!new_ie_len) { + if (mbssid_info.split_prof_continue) { + qdf_mem_free(split_prof_start); + split_prof_start = NULL; + } continue; + } new_frame_len = frame_len - ielen + new_ie_len; if (new_frame_len < 0) { - if (mbssid_info.split_prof_continue) + if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); + split_prof_start = NULL; + } qdf_mem_free(new_ie); scm_err("Invalid frame:Stop MBSSIE parsing"); scm_err("Frame_len: %zu,ielen:%u,new_ie_len:%u", @@ -2550,8 +2560,10 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, new_frame = qdf_mem_malloc(new_frame_len); if (!new_frame) { - if (mbssid_info.split_prof_continue) + if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); + split_prof_start = NULL; + } qdf_mem_free(new_ie); scm_err_rl("Malloc for new_frame failed"); scm_err_rl("split_prof_continue: %d", @@ -2591,6 +2603,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, if (QDF_IS_STATUS_ERROR(status)) { if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); + split_prof_start = NULL; qdf_mem_zero(&mbssid_info, sizeof(mbssid_info)); } @@ -2601,8 +2614,10 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, break; } /* scan entry makes its own copy so free the frame*/ - if (mbssid_info.split_prof_continue) + if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); + split_prof_start = NULL; + } qdf_mem_free(new_frame); } @@ -2610,6 +2625,9 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, } qdf_mem_free(new_ie); + if (split_prof_start) + qdf_mem_free(split_prof_start); + return QDF_STATUS_SUCCESS; } From d400de634f2666cf9ecab0aaef302edf4a3165a4 Mon Sep 17 00:00:00 2001 From: Paul Zhang Date: Thu, 17 Aug 2023 16:20:01 +0800 Subject: [PATCH 06/15] qcacmn: Fix use-after-free issue in util_scan_parse_mbssid In some scenario, mbssid_info->prof_residue could be set to true, hence mbssid_info->split_prof_continue will also be set to true. Then for the next loop if buffer split_prof_start is freed but split_prof_end does not reinitialize to NULL, then use-after-free happens. To address this issue, reinitialize split_prof_end properly when split_prof_start is freed. Change-Id: Iad7448868cfa4c2dd7922f6c1b2622cf20a6a28c CRs-Fixed: 3583521 --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index dc3791c1f1a6..7ffe30b413d1 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2540,6 +2540,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); split_prof_start = NULL; + split_prof_end = NULL; } continue; } @@ -2604,6 +2605,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); split_prof_start = NULL; + split_prof_end = NULL; qdf_mem_zero(&mbssid_info, sizeof(mbssid_info)); } @@ -2617,6 +2619,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, if (mbssid_info.split_prof_continue) { qdf_mem_free(split_prof_start); split_prof_start = NULL; + split_prof_end = NULL; } qdf_mem_free(new_frame); } From 5336f4036a3acc2509ba6750b6422e65f613b8e8 Mon Sep 17 00:00:00 2001 From: Vinod Kumar Myadam Date: Mon, 19 Feb 2024 14:29:13 +0530 Subject: [PATCH 07/15] qcacmn: Add check to avoid NULL pointer deference in parse MBSSID In malformed beacon frame may deference the NULL pointer while parsing MBSSID IE in util_scan_parse_mbssid will lead to crash. Add check in util_scan_parse_mbsssid for split_prof_start before passing to util_gen_new_ie and assign zero to split_prof_len whenever split_prof_start freed to avoid unanticipated scenario. Change-Id: Ibb9739d6b5d1775ab52d59f9aa5050ca693cd926 CRs-Fixed: 3717571 --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 7ffe30b413d1..94a4a101a89d 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2524,6 +2524,8 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, } if (mbssid_info.split_prof_continue) { + if (!split_prof_start) + break; nontx_profile = split_prof_start; subie_len = split_prof_len; } else { @@ -2541,6 +2543,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, qdf_mem_free(split_prof_start); split_prof_start = NULL; split_prof_end = NULL; + split_prof_len = 0; } continue; } @@ -2606,6 +2609,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, qdf_mem_free(split_prof_start); split_prof_start = NULL; split_prof_end = NULL; + split_prof_len = 0; qdf_mem_zero(&mbssid_info, sizeof(mbssid_info)); } @@ -2620,6 +2624,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, qdf_mem_free(split_prof_start); split_prof_start = NULL; split_prof_end = NULL; + split_prof_len = 0; } qdf_mem_free(new_frame); } From 4afab6c41da326ed40b4f7853dcb797989278d1e Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Tue, 31 Oct 2023 23:53:59 +0530 Subject: [PATCH 08/15] qcacmn: Update BSS score calculation based on Security Profile Update BSS score calculation to consider security profile. Change-Id: I120774ce2472442ebba15e098b4089f8a17cbfc5 CRs-Fixed: 3782206 --- .../core/src/wlan_cm_bss_scoring.c | 104 +++++++++++++++++- .../dispatcher/inc/wlan_cm_bss_score_param.h | 16 ++- 2 files changed, 113 insertions(+), 7 deletions(-) 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 843c042f6cc9..04d9f3db9d7c 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 @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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 @@ -82,6 +82,7 @@ #define CM_CHAN_WIDTH_WEIGHTAGE 12 #define CM_CHAN_BAND_WEIGHTAGE 2 #define CM_NSS_WEIGHTAGE 16 +#define CM_SECURITY_WEIGHTAGE 4 #define CM_BEAMFORMING_CAP_WEIGHTAGE 2 #define CM_PCL_WEIGHT 10 #define CM_CHANNEL_CONGESTION_WEIGHTAGE 5 @@ -93,6 +94,21 @@ #define CM_MAX_PCT_SCORE 100 #define CM_MAX_INDEX_PER_INI 4 +/** + * This macro give percentage value of security_weightage to be used as per + * security Eg if AP security is WPA 10% will be given for AP. + * + * Indexes are defined in this way. + * 0 Index (BITS 0-7): WPA - Def 25% + * 1 Index (BITS 8-15): WPA2- Def 50% + * 2 Index (BITS 16-23): WPA3- Def 100% + * 3 Index (BITS 24-31): reserved + * + * if AP security is Open/WEP 0% will be given for AP + * These percentage values are stored in HEX. For any index max value, can be 64 + */ +#define CM_SECURITY_INDEX_WEIGHTAGE 0x00643219 + #define CM_BEST_CANDIDATE_MAX_BSS_SCORE (CM_BEST_CANDIDATE_MAX_WEIGHT * 100) #define CM_AVOID_CANDIDATE_MIN_SCORE 1 @@ -535,6 +551,68 @@ static int32_t cm_calculate_nss_score(struct wlan_objmgr_psoc *psoc, prorated_pct) / CM_MAX_PCT_SCORE; } +static int32_t cm_calculate_security_score(struct scoring_cfg *score_config, + struct security_info neg_sec_info) +{ + uint32_t authmode, key_mgmt, ucastcipherset; + uint8_t score_pct = 0; + + authmode = neg_sec_info.authmodeset; + key_mgmt = neg_sec_info.key_mgmt; + ucastcipherset = neg_sec_info.ucastcipherset; + + if (QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_FILS_SK) || + QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_SAE) || + QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_CCKM) || + QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_RSNA) || + QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_8021X)) { + if (QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE) || + QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192) || + QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256) || + QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384) || + QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE) || + QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_DPP) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) { + /*If security is WPA3, consider score_pct = 100%*/ + score_pct = CM_GET_SCORE_PERCENTAGE( + score_config->security_weight_per_index, + CM_SECURITY_WPA3_INDEX); + } else if (QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_FT_PSK) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) || + QDF_HAS_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) { + /*If security is WPA2, consider score_pct = 50%*/ + score_pct = CM_GET_SCORE_PERCENTAGE( + score_config->security_weight_per_index, + CM_SECURITY_WPA2_INDEX); + } + } else if (QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_SHARED) || + QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_WPA) || + QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_WAPI)) { + /*If security is WPA, consider score_pct = 25%*/ + score_pct = CM_GET_SCORE_PERCENTAGE( + score_config->security_weight_per_index, + CM_SECURITY_WPA_INDEX); + } + + return (score_config->weight_config.security_weightage * score_pct) / + CM_MAX_PCT_SCORE; +} + #ifdef WLAN_POLICY_MGR_ENABLE static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc, qdf_freq_t bss_channel_freq, @@ -1401,6 +1479,7 @@ static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, int32_t beamformee_score = 0; int32_t band_score = 0; int32_t nss_score = 0; + int32_t security_score = 0; int32_t congestion_score = 0; int32_t congestion_pct = 0; int32_t oce_wan_score = 0; @@ -1581,7 +1660,16 @@ static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, prorated_pcnt, sta_nss); score += nss_score; - mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d su bfer %d phy %d air time frac %d qbss %d cong_pct %d NSS %d ap_tx_pwr_dbm %d oce_subnet_id_present %d sae_pk_cap_present %d prorated_pcnt %d", + /* + * Since older FW will stick to the single AKM for roaming, + * no need to check the fw capability. + */ + security_score = cm_calculate_security_score(score_config, + entry->neg_sec_info); + + score += security_score; + + mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d su bfer %d phy %d air time frac %d qbss %d cong_pct %d NSS %d ap_tx_pwr_dbm %d oce_subnet_id_present %d sae_pk_cap_present %d prorated_pcnt %d keymgmt 0x%x", QDF_MAC_ADDR_REF(entry->bssid.bytes), entry->channel.chan_freq, entry->rssi_raw, util_scan_entry_htcap(entry) ? 1 : 0, @@ -1590,14 +1678,15 @@ static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, entry->phy_mode, entry->air_time_fraction, entry->qbss_chan_load, congestion_pct, entry->nss, ap_tx_pwr_dbm, oce_subnet_id_present, - sae_pk_cap_present, prorated_pcnt); + sae_pk_cap_present, prorated_pcnt, + entry->neg_sec_info.key_mgmt); - mlme_nofl_debug("Scores: rssi %d pcl %d ht %d vht %d he %d bfee %d bw %d band %d congestion %d nss %d oce wan %d oce ap tx pwr %d subnet %d sae_pk %d TOTAL %d", + mlme_nofl_debug("Scores: rssi %d pcl %d ht %d vht %d he %d bfee %d bw %d band %d congestion %d nss %d oce wan %d oce ap tx pwr %d subnet %d sae_pk %d security %d TOTAL %d", rssi_score, pcl_score, ht_score, vht_score, he_score, beamformee_score, bandwidth_score, band_score, congestion_score, nss_score, oce_wan_score, oce_ap_tx_pwr_score, oce_subnet_id_score, - sae_pk_score, score); + sae_pk_score, security_score, score); entry->bss_score = score; @@ -2019,6 +2108,7 @@ void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_OCE_SUBNET_ID_WEIGHTAGE); score_cfg->weight_config.sae_pk_ap_weightage = cfg_get(psoc, CFG_SAE_PK_AP_WEIGHTAGE); + score_cfg->weight_config.security_weightage = CM_SECURITY_WEIGHTAGE; total_weight = score_cfg->weight_config.rssi_weightage + score_cfg->weight_config.ht_caps_weightage + @@ -2033,7 +2123,8 @@ void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc, score_cfg->weight_config.oce_wan_weightage + score_cfg->weight_config.oce_ap_tx_pwr_weightage + score_cfg->weight_config.oce_subnet_id_weightage + - score_cfg->weight_config.sae_pk_ap_weightage; + score_cfg->weight_config.sae_pk_ap_weightage + + score_cfg->weight_config.security_weightage; /* * If configured weights are greater than max weight, @@ -2134,4 +2225,5 @@ void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_VENDOR_ROAM_SCORE_ALGORITHM); score_cfg->check_assoc_disallowed = true; cm_fill_6ghz_params(psoc, score_cfg); + score_cfg->security_weight_per_index = CM_SECURITY_INDEX_WEIGHTAGE; } 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 55388bd0b9d1..5ddb522b0923 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 @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. 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 @@ -41,6 +41,7 @@ * @oce_ap_tx_pwr_weightage: OCE AP tx power weigtage * @oce_subnet_id_weightage: OCE subnet id weigtage * @sae_pk_ap_weightage: SAE-PK AP weigtage + * @security_weightage: Security weightage */ struct weight_cfg { uint8_t rssi_weightage; @@ -57,6 +58,7 @@ struct weight_cfg { uint8_t oce_ap_tx_pwr_weightage; uint8_t oce_subnet_id_weightage; uint8_t sae_pk_ap_weightage; + uint8_t security_weightage; }; /** @@ -132,6 +134,8 @@ struct per_slot_score { * @check_6ghz_security: check security for 6Ghz candidate * @standard_6ghz_conn_policy: check for 6 GHz standard connection policy * @key_mgmt_mask_6ghz: user configurable mask for 6ghz AKM + * @roam_tgt_score_cap: Roam score capability + * @security_weight_per_index: security weight per index */ struct scoring_cfg { struct weight_cfg weight_config; @@ -147,6 +151,8 @@ struct scoring_cfg { uint8_t check_6ghz_security; uint8_t standard_6ghz_conn_policy:1; uint32_t key_mgmt_mask_6ghz; + uint32_t roam_tgt_score_cap; + uint32_t security_weight_per_index; }; /** @@ -207,6 +213,14 @@ wlan_blacklist_action_on_bssid(struct wlan_objmgr_pdev *pdev, } #endif +enum cm_security_idx { + CM_SECURITY_WPA_INDEX, + CM_SECURITY_WPA2_INDEX, + CM_SECURITY_WPA3_INDEX, + CM_SECURITY_WPA_OPEN_WEP_INDEX, + CM_MAX_SECURITY_INDEX +}; + /** * wlan_cm_calculate_bss_score() - calculate bss score for the scan list * @pdev: pointer to pdev object From c0567bd086f6849041923f48301bc00b040e0956 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Wed, 29 Nov 2023 20:05:37 +0530 Subject: [PATCH 09/15] qcacmn: Update key management after bss create response Add support to update key management with higher security after BSS create response. Also, Currenlty if there are multiple AKM and ucast cipher. Host overwrites AKM and ucast cipher value with the new one. Instead of overwrite, add support to do ORing to keep all values. Change-Id: I679a86debef649efbce1a08b60512d127f7fbbee CRs-Fixed: 3782223 --- .../crypto/inc/wlan_crypto_global_api.h | 21 ++++++++++++++++++- .../crypto/inc/wlan_crypto_global_def.h | 5 +++-- .../crypto/src/wlan_crypto_global_api.c | 16 ++++---------- umac/scan/core/src/wlan_scan_filter.c | 3 ++- 4 files changed, 29 insertions(+), 16 deletions(-) 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 4f1eaf957603..a9741e6367b9 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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 @@ -1130,4 +1130,23 @@ wlan_crypto_set_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev, QDF_STATUS wlan_crypto_create_fils_rik(uint8_t *rrk, uint8_t rrk_len, uint8_t *rik, uint32_t *rik_len); #endif /* WLAN_FEATURE_FILS_SK */ + +/** + * wlan_crypto_rsn_suite_to_cipher - This API converts a RSN cipher selector OUI + * to an internal cipher algorithm. Where appropriate we also record any key + * length. + * @sel: input RSN suite + * + * Return: cipher suite value + */ +int32_t wlan_crypto_rsn_suite_to_cipher(const uint8_t *sel); + +/** + * wlan_crypto_rsn_suite_to_keymgmt() - This API converts an RSN key management/ + * authentication algorithm to an internal code. + * @sel: input RSN suite + * + * Return: keymgmt value + */ +int32_t wlan_crypto_rsn_suite_to_keymgmt(const uint8_t *sel); #endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */ 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 df72eff262b8..63a31975100a 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -157,7 +158,7 @@ typedef enum wlan_crypto_auth_mode { WLAN_CRYPTO_AUTH_SAE = 9, WLAN_CRYPTO_AUTH_FILS_SK = 10, /** Keep WLAN_CRYPTO_AUTH_MAX at the end. */ - WLAN_CRYPTO_AUTH_MAX = WLAN_CRYPTO_AUTH_FILS_SK, + WLAN_CRYPTO_AUTH_MAX, } wlan_crypto_auth_mode; /* crypto capabilities */ @@ -223,7 +224,7 @@ typedef enum wlan_crypto_key_mgmt { WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384 = 25, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384 = 26, /** Keep WLAN_CRYPTO_KEY_MGMT_MAX at the end. */ - WLAN_CRYPTO_KEY_MGMT_MAX = WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384, + WLAN_CRYPTO_KEY_MGMT_MAX, } wlan_crypto_key_mgmt; enum wlan_crypto_key_type { 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 6b496baa3dbf..5206b265b05f 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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 @@ -2553,12 +2553,7 @@ static int32_t wlan_crypto_wpa_suite_to_keymgmt(const uint8_t *sel) return status; } -/* - * Convert a RSN cipher selector OUI to an internal - * cipher algorithm. Where appropriate we also - * record any key length. - */ -static int32_t wlan_crypto_rsn_suite_to_cipher(const uint8_t *sel) +int32_t wlan_crypto_rsn_suite_to_cipher(const uint8_t *sel) { uint32_t w = LE_READ_4(sel); int32_t status = -1; @@ -2588,11 +2583,8 @@ static int32_t wlan_crypto_rsn_suite_to_cipher(const uint8_t *sel) return status; } -/* - * Convert an RSN key management/authentication algorithm - * to an internal code. - */ -static int32_t wlan_crypto_rsn_suite_to_keymgmt(const uint8_t *sel) + +int32_t wlan_crypto_rsn_suite_to_keymgmt(const uint8_t *sel) { uint32_t w = LE_READ_4(sel); int32_t status = -1; diff --git a/umac/scan/core/src/wlan_scan_filter.c b/umac/scan/core/src/wlan_scan_filter.c index 73836d7bade6..24847e97e2fc 100644 --- a/umac/scan/core/src/wlan_scan_filter.c +++ b/umac/scan/core/src/wlan_scan_filter.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -490,7 +491,7 @@ static bool scm_is_security_match(struct scan_filter *filter, if (!filter->authmodeset) return scm_match_any_security(filter, db_entry, security); - for (i = 0; i <= WLAN_CRYPTO_AUTH_MAX && !match; i++) { + for (i = 0; i < WLAN_CRYPTO_AUTH_MAX && !match; i++) { if (!QDF_HAS_PARAM(filter->authmodeset, i)) continue; From 95eee69154be4bb38e41353142eb980b22bc0285 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Mon, 29 Jan 2024 20:45:05 +0530 Subject: [PATCH 10/15] qcacmn: Add support for handling the NL crypto params Added support for handling the crypto params from NL connect request that has all the supported AKMs, unicast and multicast ciphers to store them in the crypto and retrieve them later to update the scan filter params. Change-Id: I040c908c85d530ea4c86ec3e5b71044ffcf4b7d9 CRs-Fixed: 3767477 --- .../crypto/inc/wlan_crypto_global_def.h | 9 ++ .../crypto/src/wlan_crypto_global_api.c | 18 ++++ .../crypto/src/wlan_crypto_param_handling.c | 102 ++++++++++++++++++ .../crypto/src/wlan_crypto_param_handling_i.h | 77 +++++++++++++ 4 files changed, 206 insertions(+) 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 63a31975100a..f7468a78f083 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -309,6 +309,9 @@ struct wlan_crypto_pmksa { * @key_mgmt: key mgmt * @pmksa: pmksa * @rsn_caps: rsn_capability + * @orig_ucastcipher: connection request unicast ciphers + * @orig_mcastcipher: connection request multicast cipher + * @orig_key_mgmt: connection request key mgmt * * This structure holds crypto params for peer or vdev */ @@ -321,6 +324,9 @@ struct wlan_crypto_params { uint32_t key_mgmt; struct wlan_crypto_pmksa *pmksa[WLAN_CRYPTO_MAX_PMKID]; uint16_t rsn_caps; + uint32_t orig_ucastcipher; + uint32_t orig_mcastcipher; + uint32_t orig_key_mgmt; }; typedef enum wlan_crypto_param_type { @@ -332,6 +338,9 @@ typedef enum wlan_crypto_param_type { WLAN_CRYPTO_PARAM_RSN_CAP, WLAN_CRYPTO_PARAM_KEY_MGMT, WLAN_CRYPTO_PARAM_PMKSA, + WLAN_CRYPTO_PARAM_ORIG_UCAST_CIPHER, + WLAN_CRYPTO_PARAM_ORIG_MCAST_CIPHER, + WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT, } wlan_crypto_param_type; /** 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 5206b265b05f..f7ec591a6263 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -172,6 +172,15 @@ static QDF_STATUS wlan_crypto_set_param(struct wlan_crypto_params *crypto_params case WLAN_CRYPTO_PARAM_KEY_MGMT: status = wlan_crypto_set_key_mgmt(crypto_params, value); break; + case WLAN_CRYPTO_PARAM_ORIG_UCAST_CIPHER: + status = wlan_crypto_set_orig_ucastcipher(crypto_params, value); + break; + case WLAN_CRYPTO_PARAM_ORIG_MCAST_CIPHER: + status = wlan_crypto_set_orig_mcastcipher(crypto_params, value); + break; + case WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT: + status = wlan_crypto_set_orig_key_mgmt(crypto_params, value); + break; default: status = QDF_STATUS_E_INVAL; } @@ -279,6 +288,15 @@ static int32_t wlan_crypto_get_param_value(wlan_crypto_param_type param, case WLAN_CRYPTO_PARAM_KEY_MGMT: value = wlan_crypto_get_key_mgmt(crypto_params); break; + case WLAN_CRYPTO_PARAM_ORIG_UCAST_CIPHER: + value = wlan_crypto_get_orig_ucastcipher(crypto_params); + break; + case WLAN_CRYPTO_PARAM_ORIG_MCAST_CIPHER: + value = wlan_crypto_get_orig_mcastcipher(crypto_params); + break; + case WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT: + value = wlan_crypto_get_orig_key_mgmt(crypto_params); + break; default: value = -1; } diff --git a/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c b/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c index 33d24db046d3..68b79f07e87e 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -302,3 +303,104 @@ int32_t wlan_crypto_get_key_mgmt(struct wlan_crypto_params *crypto_params) { return crypto_params->key_mgmt; } + +/** + * wlan_crypto_set_orig_ucastcipher - called by ucfg to configure connection + * request unicast ciphers in vdev + * @crypto_params: pointer to crypto params structure + * @value: bitmap value of all supported unicast ciphers + * + * This function gets called from ucfg to configure unicast ciphers in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_ucastcipher(struct wlan_crypto_params *crypto_params, + uint32_t value) +{ + crypto_params->orig_ucastcipher = value; + + return QDF_STATUS_SUCCESS; +} + +/** + * wlan_crypto_get_orig_ucastcipher - called by ucfg to get connection request + * ucastcipher value from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get supported unicast ciphers + * + * Return: bitmap value of all supported unicast ciphers + */ +int32_t +wlan_crypto_get_orig_ucastcipher(struct wlan_crypto_params *crypto_params) +{ + return crypto_params->orig_ucastcipher; +} + +/** + * wlan_crypto_set_orig_mcastcipher - called by ucfg to configure connection + * request mcastcipher in vdev + * @crypto_params: pointer to crypto params structure + * @value: mcast cipher value. + * + * This function gets called from ucfg to configure mcastcipher in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_mcastcipher(struct wlan_crypto_params *crypto_params, + wlan_crypto_cipher_type value) +{ + crypto_params->orig_mcastcipher = value; + + return QDF_STATUS_SUCCESS; +} + +/** + * wlan_crypto_get_orig_mcastcipher - called by ucfg to get connection request + * mcastcipher value from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get mcastcipher of particular vdev + * + * Return: mcast cipher + */ +int32_t +wlan_crypto_get_orig_mcastcipher(struct wlan_crypto_params *crypto_params) +{ + return crypto_params->orig_mcastcipher; +} + +/** + * wlan_crypto_set_orig_key_mgmt - called by ucfg to configure connection + * request key_mgmt in vdev + * @crypto_params: pointer to crypto params structure + * @value: bitmap value of all supported AKMs + * + * This function gets called from ucfg to configure AKMs in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_key_mgmt(struct wlan_crypto_params *crypto_params, + uint32_t value) +{ + crypto_params->orig_key_mgmt = value; + + return QDF_STATUS_SUCCESS; +} + +/** + * wlan_crypto_get_orig_key_mgmt - called by ucfg to get connection request + * key mgmt value from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get supported AKMs + * + * Return: bitmap value of all supported AKMs + */ +int32_t wlan_crypto_get_orig_key_mgmt(struct wlan_crypto_params *crypto_params) +{ + return crypto_params->orig_key_mgmt; +} diff --git a/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h b/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h index d6198b4b2aa1..17d0edd0daf5 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -179,4 +180,80 @@ QDF_STATUS wlan_crypto_set_key_mgmt(struct wlan_crypto_params *crypto_params, * Return: bitmap value of all supported unicast ciphers */ int32_t wlan_crypto_get_key_mgmt(struct wlan_crypto_params *crypto_params); + +/** + * wlan_crypto_set_orig_ucastcipher - called by ucfg to configure connection + * request unicast ciphers in vdev + * @crypto_params: pointer to crypto params structure + * @value: bitmap value of all supported unicast ciphers + * + * This function gets called from ucfg to configure unicast ciphers in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_ucastcipher(struct wlan_crypto_params *crypto_params, + uint32_t value); + +/** + * wlan_crypto_get_orig_ucastcipher - called by ucfg to get connection request + * unicast cipher from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get supported unicast ciphers + * + * Return: bitmap value of all supported unicast ciphers + */ +int32_t +wlan_crypto_get_orig_ucastcipher(struct wlan_crypto_params *crypto_params); + +/** + * wlan_crypto_set_orig_mcastcipher - called by ucfg to configure connection + * request mcastcipher in vdev + * @crypto_params: pointer to crypto params structure + * @wlan_crypto_cipher_type: mcast cipher value. + * + * This function gets called from ucfg to configure mcastcipher in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_mcastcipher(struct wlan_crypto_params *crypto_params, + wlan_crypto_cipher_type cipher); +/** + * wlan_crypto_get_orig_mcastcipher - called by ucfg to get connection request + * mcastcipher from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get mcastcipher of particular vdev + * + * Return: mcast cipher + */ +int32_t +wlan_crypto_get_orig_mcastcipher(struct wlan_crypto_params *crypto_params); + +/** + * wlan_crypto_set_orig_key_mgmt - called by ucfg to configure connection + * request key_mgmt in vdev + * @crypto_params: pointer to crypto params structure + * @value: bitmap value of all supported AKMs + * + * This function gets called from ucfg to configure AKMs in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_key_mgmt(struct wlan_crypto_params *crypto_params, + uint32_t value); + +/** + * wlan_crypto_get_orig_key_mgmt - called by ucfg to get connection request key + * mgmt from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get supported AKMs + * + * Return: bitmap value of all supported AKMs + */ +int32_t wlan_crypto_get_orig_key_mgmt(struct wlan_crypto_params *crypto_params); #endif /* __WLAN_CRYPTO_PARAM_HANDLING_I_H_ */ From f363c9105d3f35584c376daffd68e6c35f904839 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Tue, 27 Feb 2024 18:14:28 +0530 Subject: [PATCH 11/15] qcacmn: Send the user configured MFP state in RSO command Currently the user configured MFP state that comes from the userspace in connect request is not handled or processed. Instead the RSN caps from assoc IE of connect request is inter- sected with AP RSN caps and sent to Firmware using RSO command. This RSN caps is used in FW in selecting a roam candidate, which was causing the cross AKM (eg:SAE -> PSK) roam fail. Hence, use the user configured MFP value in sending the RSN caps to Firmware. Change-Id: I3facfcf3616667b4749109d26d924c3fb1537494 CRs-Fixed: 3606069 --- .../cmn_defs/inc/wlan_cmn_ieee80211.h | 3 +- .../crypto/inc/wlan_crypto_global_def.h | 3 ++ .../crypto/src/wlan_crypto_global_api.c | 6 ++++ .../crypto/src/wlan_crypto_param_handling.c | 33 +++++++++++++++++++ .../crypto/src/wlan_crypto_param_handling_i.h | 23 +++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index f4ccb035f530..7bb3e657a8d9 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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 @@ -918,6 +918,7 @@ enum wlan_status_code { #define WLAN_ASE_SHA256_PSK 0x100 #define WLAN_ASE_WPS 0x200 +#define RSN_CAP_MFP_DISABLED 0x00 #define RSN_CAP_MFP_CAPABLE 0x80 #define RSN_CAP_MFP_REQUIRED 0x40 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 f7468a78f083..d5f386bef272 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -312,6 +312,7 @@ struct wlan_crypto_pmksa { * @orig_ucastcipher: connection request unicast ciphers * @orig_mcastcipher: connection request multicast cipher * @orig_key_mgmt: connection request key mgmt + * @orig_rsn_caps: connection request rsn_capability * * This structure holds crypto params for peer or vdev */ @@ -327,6 +328,7 @@ struct wlan_crypto_params { uint32_t orig_ucastcipher; uint32_t orig_mcastcipher; uint32_t orig_key_mgmt; + uint16_t orig_rsn_caps; }; typedef enum wlan_crypto_param_type { @@ -341,6 +343,7 @@ typedef enum wlan_crypto_param_type { WLAN_CRYPTO_PARAM_ORIG_UCAST_CIPHER, WLAN_CRYPTO_PARAM_ORIG_MCAST_CIPHER, WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT, + WLAN_CRYPTO_PARAM_ORIG_RSN_CAP, } wlan_crypto_param_type; /** 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 f7ec591a6263..8bf19d70cbb6 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -181,6 +181,9 @@ static QDF_STATUS wlan_crypto_set_param(struct wlan_crypto_params *crypto_params case WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT: status = wlan_crypto_set_orig_key_mgmt(crypto_params, value); break; + case WLAN_CRYPTO_PARAM_ORIG_RSN_CAP: + status = wlan_crypto_set_orig_rsn_cap(crypto_params, value); + break; default: status = QDF_STATUS_E_INVAL; } @@ -297,6 +300,9 @@ static int32_t wlan_crypto_get_param_value(wlan_crypto_param_type param, case WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT: value = wlan_crypto_get_orig_key_mgmt(crypto_params); break; + case WLAN_CRYPTO_PARAM_ORIG_RSN_CAP: + value = wlan_crypto_get_orig_rsn_cap(crypto_params); + break; default: value = -1; } diff --git a/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c b/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c index 68b79f07e87e..12a78b4334c9 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c @@ -404,3 +404,36 @@ int32_t wlan_crypto_get_orig_key_mgmt(struct wlan_crypto_params *crypto_params) { return crypto_params->orig_key_mgmt; } + +/** + * wlan_crypto_set_orig_rsn_cap - called by ucfg to configure connection + * request RSN capabilities in vdev + * @crypto_params: pointer to crypto params structure + * @value: bitmap value of all supported RSN capabilities + * + * This function gets called from ucfg to configure RSN caps in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_crypto_set_orig_rsn_cap(struct wlan_crypto_params *crypto_params, + uint32_t value) +{ + crypto_params->orig_rsn_caps = value; + + return QDF_STATUS_SUCCESS; +} + +/** + * wlan_crypto_get_orig_rsn_cap - called by ucfg to get connection request + * RSN capabilities from vdev + * @crypto_params: pointer to crypto params structure + * + * This function gets called from ucfg to get supported RSN capabilities + * + * Return: bitmap value of all supported RSN caps + */ +int32_t wlan_crypto_get_orig_rsn_cap(struct wlan_crypto_params *crypto_params) +{ + return crypto_params->orig_rsn_caps; +} diff --git a/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h b/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h index 17d0edd0daf5..718001866cad 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_param_handling_i.h @@ -256,4 +256,27 @@ wlan_crypto_set_orig_key_mgmt(struct wlan_crypto_params *crypto_params, * Return: bitmap value of all supported AKMs */ int32_t wlan_crypto_get_orig_key_mgmt(struct wlan_crypto_params *crypto_params); + +/** + * wlan_crypto_set_orig_rsn_cap - called by ucfg to configure + * RSN cap in vdev + * @crypto_params: pointer to crypto params + * @value: bitmap value of all supported RSN cap + * + * This function gets called from ucfg to configure RSN cap in vdev + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS wlan_crypto_set_orig_rsn_cap(struct wlan_crypto_params *crypto_params, + uint32_t value); + +/** + * wlan_crypto_get_orig_rsn_cap - called by ucfg to get RSN cap from vdev + * @crypto_params: pointer to crypto params + * + * This function gets called from ucfg to get supported RSN cap + * + * Return: bitmap value of all supported RSN cap + */ +int32_t wlan_crypto_get_orig_rsn_cap(struct wlan_crypto_params *crypto_params); #endif /* __WLAN_CRYPTO_PARAM_HANDLING_I_H_ */ From aab3fa668d969b6778f66efd5a891df0b814d8df Mon Sep 17 00:00:00 2001 From: Sheenam Monga Date: Tue, 30 Apr 2024 10:58:07 +0530 Subject: [PATCH 12/15] qcacmn: Add length checks for noninheritance_ie In util_scan_find_noninheritance_ie API, ies[ELEM_ID_EXTN_POS] may lead to OOB access if len==MIN_IE_LEN. util_parse_noninheritance_list may lead to OOB read access extn_elem[ELEM_ID_LIST_LEN_POS] Fix is to add length checks and add sub_copy and length subie_len checks before accessing extn_elem to avoid any OOB read. Change-Id: I7758c6e4d8d568a5050011603b48a23e0b11da94 CRs-Fixed: 3717569 --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 94a4a101a89d..c7e8d2bfa50b 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -1825,7 +1825,8 @@ static uint8_t if (!ies) return NULL; - while (len >= MIN_IE_LEN && len >= ies[TAG_LEN_POS] + MIN_IE_LEN) { + while ((len >= MIN_IE_LEN + 1) && len >= ies[TAG_LEN_POS] + MIN_IE_LEN) + { if ((ies[ID_POS] == elem_id) && (ies[ELEM_ID_EXTN_POS] == WLAN_EXTN_ELEMID_NONINHERITANCE)) { @@ -2016,9 +2017,11 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, extn_elem = util_scan_find_noninheritance_ie(WLAN_ELEMID_EXTN_ELEM, sub_copy, subie_len); - if (extn_elem && extn_elem[TAG_LEN_POS]) { - util_parse_noninheritance_list(extn_elem, &elem_list, - &extn_elem_list, &ninh); + if (extn_elem && extn_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) { + if (((extn_elem + extn_elem[1] + MIN_IE_LEN) - sub_copy) + < subie_len) + util_parse_noninheritance_list(extn_elem, &elem_list, + &extn_elem_list, &ninh); } /* go through IEs in ie (skip SSID) and subelement, From 9a7916c74a445ff3ed1b1c494e2d8e1039c11b0a Mon Sep 17 00:00:00 2001 From: Krupali Dhanvijay Date: Fri, 2 Feb 2024 12:29:05 +0530 Subject: [PATCH 13/15] qcacmn: Fix OOB reads in util_gen_new_ie In util_gen_new_ie, there are several possible out-of-bound reads with invalid information elements such as improper/missing check when updating tmp_old, missing check prior to starting while loop and missing length check. To fix these OOB issues add and improve length checks in util_gen_new_ie. Change-Id: I39b9cd82ab6a7bd1a4c8d7cd5039a998a290b85f CRs-Fixed: 3717568 --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index c7e8d2bfa50b..c9fcd7db83a0 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2030,6 +2030,11 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen); tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + MIN_IE_LEN : ie; + if (((tmp_old + MIN_IE_LEN) - ie) >= ielen) { + qdf_mem_free(sub_copy); + return 0; + } + while (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) <= ielen) { ninh.non_inh_ie_found = 0; if (ninh.non_inherit) { @@ -2051,6 +2056,9 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, } if (ninh.non_inh_ie_found || (tmp_old[0] == 0)) { + if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= + (ielen - MIN_IE_LEN)) + break; tmp_old += tmp_old[1] + MIN_IE_LEN; continue; } @@ -2105,7 +2113,8 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, MIN_IE_LEN; } } - } else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM) { + } else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM && + tmp_rem_len >= (MIN_IE_LEN + 1)) { if (tmp_old[PAYLOAD_START_POS] == tmp[PAYLOAD_START_POS]) { /* same ie, copy from subelement */ @@ -2139,7 +2148,8 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, } } - if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= ielen) + if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= + (ielen - MIN_IE_LEN)) break; tmp_old += tmp_old[1] + MIN_IE_LEN; From ec7a4981c158d3580705bb2bfe62cfb37cb611da Mon Sep 17 00:00:00 2001 From: Krupali Dhanvijay Date: Fri, 2 Feb 2024 12:29:05 +0530 Subject: [PATCH 14/15] qcacmn: Fix OOB reads in util_gen_new_ie In util_gen_new_ie, there are several possible out-of-bound reads with invalid information elements such as improper/missing check when updating tmp_old, missing check prior to starting while loop and missing length check. To fix these OOB issues add and improve length checks in util_gen_new_ie. Change-Id: I39b9cd82ab6a7bd1a4c8d7cd5039a998a290b85f CRs-Fixed: 3717568 (cherry picked from commit 9a7916c74a445ff3ed1b1c494e2d8e1039c11b0a) --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 94a4a101a89d..3cc584057332 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2027,6 +2027,11 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen); tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + MIN_IE_LEN : ie; + if (((tmp_old + MIN_IE_LEN) - ie) >= ielen) { + qdf_mem_free(sub_copy); + return 0; + } + while (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) <= ielen) { ninh.non_inh_ie_found = 0; if (ninh.non_inherit) { @@ -2048,6 +2053,9 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, } if (ninh.non_inh_ie_found || (tmp_old[0] == 0)) { + if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= + (ielen - MIN_IE_LEN)) + break; tmp_old += tmp_old[1] + MIN_IE_LEN; continue; } @@ -2102,7 +2110,8 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, MIN_IE_LEN; } } - } else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM) { + } else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM && + tmp_rem_len >= (MIN_IE_LEN + 1)) { if (tmp_old[PAYLOAD_START_POS] == tmp[PAYLOAD_START_POS]) { /* same ie, copy from subelement */ @@ -2136,7 +2145,8 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, } } - if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= ielen) + if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= + (ielen - MIN_IE_LEN)) break; tmp_old += tmp_old[1] + MIN_IE_LEN; From d94548fc722bab61a86c47e802e990fe79ce7b40 Mon Sep 17 00:00:00 2001 From: Sheenam Monga Date: Tue, 30 Apr 2024 10:58:07 +0530 Subject: [PATCH 15/15] qcacmn: Add length checks for noninheritance_ie In util_scan_find_noninheritance_ie API, ies[ELEM_ID_EXTN_POS] may lead to OOB access if len==MIN_IE_LEN. util_parse_noninheritance_list may lead to OOB read access extn_elem[ELEM_ID_LIST_LEN_POS] Fix is to add length checks and add sub_copy and length subie_len checks before accessing extn_elem to avoid any OOB read. Change-Id: I7758c6e4d8d568a5050011603b48a23e0b11da94 CRs-Fixed: 3717569 (cherry picked from commit aab3fa668d969b6778f66efd5a891df0b814d8df) --- umac/scan/dispatcher/src/wlan_scan_utils_api.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 94a4a101a89d..c7e8d2bfa50b 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -1825,7 +1825,8 @@ static uint8_t if (!ies) return NULL; - while (len >= MIN_IE_LEN && len >= ies[TAG_LEN_POS] + MIN_IE_LEN) { + while ((len >= MIN_IE_LEN + 1) && len >= ies[TAG_LEN_POS] + MIN_IE_LEN) + { if ((ies[ID_POS] == elem_id) && (ies[ELEM_ID_EXTN_POS] == WLAN_EXTN_ELEMID_NONINHERITANCE)) { @@ -2016,9 +2017,11 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, extn_elem = util_scan_find_noninheritance_ie(WLAN_ELEMID_EXTN_ELEM, sub_copy, subie_len); - if (extn_elem && extn_elem[TAG_LEN_POS]) { - util_parse_noninheritance_list(extn_elem, &elem_list, - &extn_elem_list, &ninh); + if (extn_elem && extn_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) { + if (((extn_elem + extn_elem[1] + MIN_IE_LEN) - sub_copy) + < subie_len) + util_parse_noninheritance_list(extn_elem, &elem_list, + &extn_elem_list, &ninh); } /* go through IEs in ie (skip SSID) and subelement,