diff --git a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h index 05b4dfc2ec31..9a027bc6a11f 100644 --- a/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h +++ b/drivers/staging/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-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 @@ -202,6 +202,8 @@ struct wlan_cm_roam_vendor_btm_params { * floor in dB * @bg_rssi_threshold: Value of rssi threshold to trigger roaming * after background scan. + * @num_allowed_authmode: Number of allowerd authmode + * @allowed_authmode: List of allowed authmode other than connected */ struct ap_profile { uint32_t flags; @@ -213,6 +215,8 @@ struct ap_profile { uint32_t rsn_mcastmgmtcipherset; uint32_t rssi_abs_thresh; uint8_t bg_rssi_threshold; + uint32_t num_allowed_authmode; + uint32_t allowed_authmode[WLAN_CRYPTO_AUTH_MAX]; }; /** @@ -261,6 +265,14 @@ struct ap_profile { * @rssi_scoring: RSSI scoring information. * @esp_qbss_scoring: ESP/QBSS scoring percentage information * @oce_wan_scoring: OCE WAN metrics percentage information + * @security_weightage: Security(WPA/WPA2/WPA3) weightage out of + * total score in % + * @security_index_score: Security scoring percentage information. + * BITS 0-7 :- It contains scoring percentage of WPA security + * BITS 8-15 :- It contains scoring percentage of WPA2 security + * BITS 16-23 :- It contains scoring percentage of WPA3 security + * BITS 24-31 :- reserved + * The value of each index must be 0-100 */ struct scoring_param { uint32_t disable_bitmap; @@ -288,6 +300,8 @@ struct scoring_param { struct rssi_config_score rssi_scoring; struct per_slot_score esp_qbss_scoring; struct per_slot_score oce_wan_scoring; + int32_t security_weightage; + uint32_t security_index_score; }; /** diff --git a/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c b/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c index 0c6e35797f17..a401cb56ea0e 100644 --- a/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c +++ b/drivers/staging/qcacld-3.0/components/wmi/src/wmi_unified_roam_tlv.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-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 @@ -2497,9 +2497,11 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, wmi_roam_score_delta_param *score_delta_param; wmi_roam_cnd_min_rssi_param *min_rssi_param; enum roam_trigger_reason trig_reason; + uint32_t *authmode_list; + int i; len = sizeof(wmi_roam_ap_profile_fixed_param) + sizeof(wmi_ap_profile); - len += sizeof(*score_param); + len += sizeof(*score_param) + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE; if (!wmi_service_enabled(wmi_handle, wmi_service_configure_roam_trigger_param_support)) { @@ -2507,7 +2509,18 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, len += NUM_OF_ROAM_TRIGGERS * sizeof(*score_delta_param); len += WMI_TLV_HDR_SIZE; len += NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param); + } else { + len += 2 * WMI_TLV_HDR_SIZE; } + + if (ap_profile->profile.num_allowed_authmode) { + len += WMI_TLV_HDR_SIZE; + len += ap_profile->profile.num_allowed_authmode * + sizeof(uint32_t); + } else { + len += WMI_TLV_HDR_SIZE; + } + buf = wmi_buf_alloc(wmi_handle, len); if (!buf) return QDF_STATUS_E_NOMEM; @@ -2564,6 +2577,8 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, score_param->bw_weightage_pcnt = ap_profile->param.bw_weightage; score_param->band_weightage_pcnt = ap_profile->param.band_weightage; score_param->nss_weightage_pcnt = ap_profile->param.nss_weightage; + score_param->security_weightage_pcnt = + ap_profile->param.security_weightage; score_param->esp_qbss_weightage_pcnt = ap_profile->param.esp_qbss_weightage; score_param->beamforming_weightage_pcnt = @@ -2580,7 +2595,7 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, score_param->sae_pk_ap_weightage_pcnt = ap_profile->param.sae_pk_ap_weightage; - wmi_debug("Score params weightage: disable_bitmap %x rssi %d ht %d vht %d he %d BW %d band %d NSS %d ESP %d BF %d PCL %d OCE WAN %d APTX %d roam score algo %d subnet id %d sae-pk %d", + wmi_debug("Score params weightage: disable_bitmap %x rssi %d ht %d vht %d he %d BW %d band %d NSS %d ESP %d BF %d PCL %d OCE WAN %d APTX %d roam score algo %d subnet id %d sae-pk %d security %d", score_param->disable_bitmap, score_param->rssi_weightage_pcnt, score_param->ht_weightage_pcnt, score_param->vht_weightage_pcnt, @@ -2594,18 +2609,22 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, score_param->oce_ap_tx_pwr_weightage_pcnt, score_param->vendor_roam_score_algorithm_id, score_param->oce_ap_subnet_id_weightage_pcnt, - score_param->sae_pk_ap_weightage_pcnt); + score_param->sae_pk_ap_weightage_pcnt, + score_param->security_weightage_pcnt); score_param->bw_scoring.score_pcnt = ap_profile->param.bw_index_score; score_param->band_scoring.score_pcnt = ap_profile->param.band_index_score; score_param->nss_scoring.score_pcnt = ap_profile->param.nss_index_score; + score_param->security_scoring.score_pcnt = + ap_profile->param.security_index_score; - wmi_debug("bw_index_score %x band_index_score %x nss_index_score %x", + wmi_debug("bw_index_score %x band_index_score %x nss_index_score %x security_index_score %x", score_param->bw_scoring.score_pcnt, score_param->band_scoring.score_pcnt, - score_param->nss_scoring.score_pcnt); + score_param->nss_scoring.score_pcnt, + score_param->security_scoring.score_pcnt); score_param->rssi_scoring.best_rssi_threshold = (-1) * ap_profile->param.rssi_scoring.best_rssi_threshold; @@ -2751,7 +2770,58 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, convert_roam_trigger_reason(trig_reason); min_rssi_param->candidate_min_rssi = ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].min_rssi; + + buf_ptr += sizeof(*min_rssi_param); + } else { + /* set zero TLV's for roam_score_delta_param_list */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* set zero TLV's for roam_cnd_min_rssi_param_list */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; } + + /* set zero TLV's for roam_cnd_vendor_scoring_param */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* set zero TLV's for owe_ap_profile */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* List of Allowed authmode other than the connected akm */ + if (ap_profile->profile.num_allowed_authmode) { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (ap_profile->profile.num_allowed_authmode * + sizeof(uint32_t))); + + buf_ptr += WMI_TLV_HDR_SIZE; + + authmode_list = (uint32_t *)buf_ptr; + for (i = 0; i < ap_profile->profile.num_allowed_authmode; i++) + authmode_list[i] = + ap_profile->profile.allowed_authmode[i]; + + wmi_debug("[Allowed Authmode]: num_allowed_authmode: %d", + ap_profile->profile.num_allowed_authmode); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, + authmode_list, + ap_profile->profile.num_allowed_authmode * + sizeof(uint32_t)); + buf_ptr += ap_profile->profile.num_allowed_authmode * + sizeof(uint32_t); + } else { + /* set zero TLV's for allowed_authmode */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + } + wmi_mtrace(WMI_ROAM_AP_PROFILE, NO_SESSION, 0); status = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_ROAM_AP_PROFILE); diff --git a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c index 83d48b50c989..d0d84e40a9ce 100644 --- a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c +++ b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-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 @@ -1607,7 +1607,16 @@ static bool dp_fisa_aggregation_should_stop( HAL_RX_TLV_GET_TCP_OFFSET(rx_tlv_hdr); uint32_t cumulative_ip_len_delta = hal_cumulative_ip_len - fisa_flow->hal_cumultive_ip_len; + bool ip_csum_err = hal_rx_attn_ip_cksum_fail_get(rx_tlv_hdr); + bool tcp_udp_csum_er = hal_rx_attn_tcp_udp_cksum_fail_get(rx_tlv_hdr); + /** + * If l3/l4 checksum validation failed for MSDU, then data + * is not trust worthy to build aggregated skb, so do not + * allow for aggregation. And also in aggregated case it + * is job of driver to make sure checksum is valid before + * computing partial checksum for final aggregated skb. + * * kernel network panic if UDP data length < 12 bytes get aggregated, * no solid conclusion currently, as a SW WAR, only allow UDP * aggregation if UDP data length >= 16 bytes. @@ -1620,6 +1629,7 @@ static bool dp_fisa_aggregation_should_stop( * otherwise, current fisa flow aggregation should be stopped. */ if (fisa_flow->do_not_aggregate || + (ip_csum_err || tcp_udp_csum_er) || msdu_len < (l4_hdr_offset + FISA_MIN_L4_AND_DATA_LEN) || hal_cumulative_ip_len <= fisa_flow->hal_cumultive_ip_len || cumulative_ip_len_delta > FISA_MAX_SINGLE_CUMULATIVE_IP_LEN || diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c index 001524cb863b..8531cf162dc0 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c @@ -17123,6 +17123,17 @@ static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy) } #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) +static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy) +{ + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MFP_OPTIONAL); +} +#else +static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy) +{ +} +#endif + #ifdef WLAN_FEATURE_DSRC static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg, int *num_ch, int *ch_len) @@ -17344,6 +17355,19 @@ wlan_hdd_update_akm_suit_info(struct wiphy *wiphy) } #endif +#ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT +static void +wlan_hdd_update_max_connect_akm(struct wiphy *wiphy) +{ + wiphy->max_num_akms_connect = WLAN_CM_MAX_CONNECT_AKMS; +} +#else +static void +wlan_hdd_update_max_connect_akm(struct wiphy *wiphy) +{ +} +#endif + /* * FUNCTION: wlan_hdd_cfg80211_init * This function is called by hdd_wlan_startup() @@ -17473,6 +17497,9 @@ int wlan_hdd_cfg80211_init(struct device *dev, hdd_add_channel_switch_support(&wiphy->flags); wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS; + + wlan_hdd_update_max_connect_akm(wiphy); + wlan_hdd_cfg80211_action_frame_randomization_init(wiphy); wlan_hdd_set_nan_supported_bands(wiphy); @@ -17792,6 +17819,8 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx) mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc); if (mac_spoofing_enabled) wlan_hdd_cfg80211_scan_randomization_init(wiphy); + + wlan_hdd_set_mfp_optional(wiphy); } /** @@ -20477,12 +20506,136 @@ static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt) case WLAN_AKM_SUITE_FILS_SHA384: case WLAN_AKM_SUITE_FT_FILS_SHA256: case WLAN_AKM_SUITE_FT_FILS_SHA384: + hdd_debug("Fils AKM : %x", key_mgmt); return true; default: return false; } } +#ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT +/** + * hdd_populate_crypto_akm_type() - populate akm type for crypto + * @vdev: pointed to vdev obmgr + * @req: connect req + * + * set the crypto akm type for corresponding akm type received + * from NL + * + * Return: None + */ +static void +hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev, + const struct cfg80211_connect_params *req) +{ + QDF_STATUS status; + uint32_t i = 0; + uint32_t set_val = 0; + wlan_crypto_key_mgmt akm; + + if (req->crypto.n_connect_akm_suites) { + for (i = 0; i < req->crypto.n_connect_akm_suites && + i < WLAN_CM_MAX_CONNECT_AKMS; i++) { + akm = osif_nl_to_crypto_akm_type( + req->crypto.connect_akm_suites[i]); + + HDD_SET_BIT(set_val, akm); + } + + status = wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_KEY_MGMT, + set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to set akm type %0x to crypto", + set_val); + + status = wlan_crypto_set_vdev_param( + vdev, WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT, set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to set original akm type %0x to crypto", + set_val); + } else { + set_val = 0; + /* Reset to none */ + HDD_SET_BIT(set_val, WLAN_CRYPTO_KEY_MGMT_NONE); + wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_KEY_MGMT, + set_val); + wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT, + set_val); + } +} + +static int +hdd_get_num_akm_suites(const struct cfg80211_connect_params *req) +{ + return req->crypto.n_connect_akm_suites; +} + +static uint32_t* +hdd_get_akm_suites(const struct cfg80211_connect_params *req) +{ + return (uint32_t *)req->crypto.connect_akm_suites; +} +#else +static void +hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev, + const struct cfg80211_connect_params *req) +{ + QDF_STATUS status; + uint32_t i = 0; + uint32_t set_val = 0; + wlan_crypto_key_mgmt akm; + + if (req->crypto.n_akm_suites) { + for (i = 0; i < req->crypto.n_akm_suites && + i < NL80211_MAX_NR_AKM_SUITES; i++) { + akm = osif_nl_to_crypto_akm_type( + req->crypto.akm_suites[i]); + + HDD_SET_BIT(set_val, akm); + } + + status = wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_KEY_MGMT, + set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to set akm type %0x to crypto", + set_val); + + status = wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT, + set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to set original akm type %0x to crypto", + set_val); + } else { + set_val = 0; + /* Reset to none */ + HDD_SET_BIT(set_val, WLAN_CRYPTO_KEY_MGMT_NONE); + wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_KEY_MGMT, + set_val); + wlan_crypto_set_vdev_param(vdev, + WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT, + set_val); + } +} + +static int +hdd_get_num_akm_suites(const struct cfg80211_connect_params *req) +{ + return req->crypto.n_akm_suites; +} + +static uint32_t* +hdd_get_akm_suites(const struct cfg80211_connect_params *req) +{ + return (uint32_t *)req->crypto.akm_suites; +} +#endif + static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req) { enum nl80211_auth_type auth_type = req->auth_type; @@ -20490,11 +20643,15 @@ static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req) * Below n_akm_suites is defined as int in the kernel, even though it * is supposed to be unsigned. */ - int num_akm_suites = req->crypto.n_akm_suites; - uint32_t key_mgmt = req->crypto.akm_suites[0]; + int num_akm_suites; + uint32_t *akm_suites; + uint8_t i; enum eAniAuthType fils_auth_type = wlan_hdd_get_fils_auth_type(req->auth_type); + num_akm_suites = hdd_get_num_akm_suites(req); + akm_suites = hdd_get_akm_suites(req); + if (num_akm_suites <= 0) return false; @@ -20505,12 +20662,13 @@ static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req) (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE)) return false; - if (!wlan_hdd_is_akm_suite_fils(key_mgmt)) - return false; + for (i = 0; i < num_akm_suites; i++) { + if (!wlan_hdd_is_akm_suite_fils(akm_suites[i])) + continue; + return true; + } - hdd_debug("Fils Auth %d AKM %d", fils_auth_type, key_mgmt); - - return true; + return false; } #else @@ -20858,60 +21016,71 @@ static void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev, set_val); } -/** - * hdd_populate_crypto_akm_type() - populate akm type for crypto - * @vdev: pointed to vdev obmgr - * @akm_type: legacy akm_type - * - * set the crypto akm type for corresponding akm type received - * from NL - * - * Return: None - */ -static void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev, - u32 key_mgmt) -{ - QDF_STATUS status; - uint32_t set_val = 0; - wlan_crypto_key_mgmt crypto_akm_type = - osif_nl_to_crypto_akm_type(key_mgmt); - - HDD_SET_BIT(set_val, crypto_akm_type); - - status = wlan_crypto_set_vdev_param(vdev, - WLAN_CRYPTO_PARAM_KEY_MGMT, - set_val); - if (QDF_IS_STATUS_ERROR(status)) - hdd_err("Failed to set akm type %0x to crypto component", - set_val); -} - /** * hdd_populate_crypto_cipher_type() - populate cipher type for crypto - * @cipher: legacy cipher type * @vdev: pointed to vdev obmgr - * @cipher_param_type: param type, UCST/MCAST + * @req: Pointer to security parameters + * @cipher_param_type: param type, UCAST/MCAST * * set the crypto cipher type for corresponding cipher type received * from NL * * Return: None */ -static void hdd_populate_crypto_cipher_type(u32 cipher, - struct wlan_objmgr_vdev *vdev, - wlan_crypto_param_type - cipher_param_type) +static void +hdd_populate_crypto_cipher_type(struct wlan_objmgr_vdev *vdev, + struct cfg80211_connect_params *req, + wlan_crypto_param_type cipher_param_type) { QDF_STATUS status; uint32_t set_val = 0; - wlan_crypto_cipher_type crypto_cipher_type = - osif_nl_to_crypto_cipher_type(cipher); + uint32_t i = 0; + wlan_crypto_cipher_type cipher = WLAN_CRYPTO_CIPHER_NONE; - HDD_SET_BIT(set_val, crypto_cipher_type); - status = wlan_crypto_set_vdev_param(vdev, cipher_param_type, set_val); - if (QDF_IS_STATUS_ERROR(status)) - hdd_debug("Failed to set cipher params %d type %0x to crypto", - cipher_param_type, set_val); + switch (cipher_param_type) { + case WLAN_CRYPTO_PARAM_UCAST_CIPHER: + for (i = 0; i < req->crypto.n_ciphers_pairwise && + i < NL80211_MAX_NR_CIPHER_SUITES; i++) { + cipher = + osif_nl_to_crypto_cipher_type(req->crypto.ciphers_pairwise[i]); + + HDD_SET_BIT(set_val, cipher); + } + status = wlan_crypto_set_vdev_param(vdev, + cipher_param_type, + set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_debug("Failed to set cipher params %d type %0x to crypto", + cipher_param_type, set_val); + break; + case WLAN_CRYPTO_PARAM_MCAST_CIPHER: + cipher = + osif_nl_to_crypto_cipher_type(req->crypto.cipher_group); + + HDD_SET_BIT(set_val, cipher); + status = wlan_crypto_set_vdev_param(vdev, cipher_param_type, + set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_debug("Failed to set cipher params %d type %0x to crypto", + cipher_param_type, set_val); + break; + default: + hdd_err("Neither of Pairwise/Groupwise cipher"); + break; + } +} + +static inline +uint8_t hdd_get_rsn_cap_mfp(enum nl80211_mfp mfp_state) +{ + switch (mfp_state) { + case NL80211_MFP_REQUIRED: + return RSN_CAP_MFP_REQUIRED; + case NL80211_MFP_OPTIONAL: + return RSN_CAP_MFP_CAPABLE; + default: + return RSN_CAP_MFP_DISABLED; + } } /** @@ -20931,38 +21100,52 @@ static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev, /* Resetting the RSN caps for every connection */ wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP, set_val); - if (req->crypto.n_akm_suites) { - hdd_populate_crypto_akm_type(vdev, req->crypto.akm_suites[0]); - } else { - /* Reset to none */ - HDD_SET_BIT(set_val, WLAN_CRYPTO_KEY_MGMT_NONE); - wlan_crypto_set_vdev_param(vdev, - WLAN_CRYPTO_PARAM_KEY_MGMT, - set_val); - } + /* Fill AKM suites */ + hdd_populate_crypto_akm_type(vdev, req); + + /* Fill pairwise cipher suites */ if (req->crypto.n_ciphers_pairwise) { - hdd_populate_crypto_cipher_type(req->crypto.ciphers_pairwise[0], - vdev, + hdd_populate_crypto_cipher_type(vdev, req, WLAN_CRYPTO_PARAM_UCAST_CIPHER); } else { set_val = 0; /* Reset to none */ HDD_SET_BIT(set_val, WLAN_CRYPTO_CIPHER_NONE); wlan_crypto_set_vdev_param(vdev, - WLAN_CRYPTO_PARAM_UCAST_CIPHER, - set_val); + WLAN_CRYPTO_PARAM_UCAST_CIPHER, + set_val); } + + /* Fill group cipher suites */ if (req->crypto.cipher_group) { - hdd_populate_crypto_cipher_type(req->crypto.cipher_group, - vdev, + hdd_populate_crypto_cipher_type(vdev, req, WLAN_CRYPTO_PARAM_MCAST_CIPHER); } else { set_val = 0; /* Reset to none */ HDD_SET_BIT(set_val, WLAN_CRYPTO_CIPHER_NONE); wlan_crypto_set_vdev_param(vdev, - WLAN_CRYPTO_PARAM_MCAST_CIPHER, - set_val); + WLAN_CRYPTO_PARAM_MCAST_CIPHER, + set_val); + } + + if (req->mfp) { + QDF_STATUS status; + + set_val = (uint32_t)hdd_get_rsn_cap_mfp(req->mfp); + + status = wlan_crypto_set_vdev_param( + vdev, + WLAN_CRYPTO_PARAM_ORIG_RSN_CAP, + set_val); + if (QDF_IS_STATUS_ERROR(status)) + hdd_debug("Failed to set original RSN caps %d to crypto", + set_val); + } else { + set_val = 0; + /* Reset to none */ + wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_ORIG_RSN_CAP, + set_val); } hdd_populate_crypto_auth_type(vdev, req); @@ -21848,13 +22031,18 @@ static inline void hdd_dump_connect_req(struct hdd_adapter *adapter, struct cfg80211_connect_params *req) { uint32_t i; + uint32_t num_akm_suites; + uint32_t *akm_suites; + + num_akm_suites = hdd_get_num_akm_suites(req); + akm_suites = hdd_get_akm_suites(req); hdd_nofl_debug("cfg80211_connect req for %s(vdevid-%d): mode %d freq %d SSID %.*s auth type %d WPA ver %d n_akm %d n_cipher %d grp_cipher %x mfp %d freq hint %d", ndev->name, adapter->vdev_id, adapter->device_mode, req->channel ? req->channel->center_freq : 0, (int)req->ssid_len, req->ssid, req->auth_type, req->crypto.wpa_versions, - req->crypto.n_akm_suites, req->crypto.n_ciphers_pairwise, + num_akm_suites, req->crypto.n_ciphers_pairwise, req->crypto.cipher_group, req->mfp, req->channel_hint ? req->channel_hint->center_freq : 0); if (req->bssid) @@ -21865,8 +22053,8 @@ static inline void hdd_dump_connect_req(struct hdd_adapter *adapter, QDF_MAC_ADDR_REF(req->bssid_hint)); hdd_dump_prev_bssid(req); - for (i = 0; i < req->crypto.n_akm_suites; i++) - hdd_nofl_debug("akm[%d] = %x", i, req->crypto.akm_suites[i]); + for (i = 0; i < num_akm_suites; i++) + hdd_nofl_debug("akm[%d] = %x", i, akm_suites[i]); for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) hdd_nofl_debug("cipher_pairwise[%d] = %x", i, diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h index f5e1d8b7fa9f..f59eccad6adf 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-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 @@ -207,6 +208,10 @@ extern const struct nla_policy wlan_hdd_wisa_cmd_policy[ #define USE_CFG80211_DEL_STA_V2 #endif +#ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT +#define WLAN_CM_MAX_CONNECT_AKMS 5 +#endif + /** * enum eDFS_CAC_STATUS: CAC status * diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_scan.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_scan.c index 7c69a2412d04..87678f34c27a 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_scan.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_scan.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2020 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 @@ -1226,9 +1226,8 @@ static int __wlan_hdd_vendor_abort_scan( if (0 != ret) return ret; - wlan_vendor_abort_scan(hdd_ctx->pdev, data, data_len); + return wlan_vendor_abort_scan(hdd_ctx->pdev, data, data_len); - return ret; } /** @@ -1249,6 +1248,8 @@ int wlan_hdd_vendor_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev, struct osif_vdev_sync *vdev_sync; int errno; + hdd_enter_dev(wdev->netdev); + errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); if (errno) return errno; diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h index 10471b7d5459..8432ca26e339 100644 --- a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h +++ b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 2 #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 8 -#define QWLAN_VERSION_EXTRA "N" +#define QWLAN_VERSION_EXTRA "R" #define QWLAN_VERSION_BUILD 34 -#define QWLAN_VERSIONSTR "2.0.8.34N" +#define QWLAN_VERSIONSTR "2.0.8.34R" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c index 7433c5275baa..80ee8867c140 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-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 @@ -1788,76 +1788,82 @@ void lim_fill_join_rsp_ht_caps(struct pe_session *session, #ifdef WLAN_FEATURE_ROAM_OFFLOAD #ifdef WLAN_FEATURE_11W -static void pe_set_rmf_caps(struct mac_context *mac_ctx, - struct pe_session *ft_session, - struct roam_offload_synch_ind *roam_synch) +/* Assoc req IE offset - Capability(2) + LI(2) */ +#define WLAN_ASSOC_REQ_IES_OFFSET 4 +/* Assoc req IE offset - Capability(2) + LI(2) + current AP address(6) */ +#define WLAN_REASSOC_REQ_IES_OFFSET 10 + +static void pe_update_crypto_params(struct mac_context *mac_ctx, + struct pe_session *ft_session, + struct roam_offload_synch_ind *roam_synch) { - uint8_t *assoc_body; - uint16_t len; - tDot11fReAssocRequest *assoc_req; - uint32_t status; - tSirMacRsnInfo rsn_ie; - uint32_t value = WPA_TYPE_OUI; + uint8_t *assoc_ies; + uint32_t assoc_ies_len; + uint8_t ies_offset = WLAN_REASSOC_REQ_IES_OFFSET; + tpSirMacMgmtHdr hdr; + const uint8_t *wpa_ie, *rsn_ie; + uint32_t wpa_oui; + struct wlan_crypto_params *crypto_params; - assoc_body = (uint8_t *)roam_synch + roam_synch->reassoc_req_offset + - sizeof(tSirMacMgmtHdr); - len = roam_synch->reassoc_req_length - sizeof(tSirMacMgmtHdr); - - assoc_req = qdf_mem_malloc(sizeof(*assoc_req)); - if (!assoc_req) - return; - - /* delegate to the framesc-generated code, */ - status = dot11f_unpack_re_assoc_request(mac_ctx, assoc_body, len, - assoc_req, false); - if (DOT11F_FAILED(status)) { - pe_err("Failed to parse a Re-association Request (0x%08x, %d bytes):", - status, len); - QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO, - assoc_body, len); - qdf_mem_free(assoc_req); - return; - } else if (DOT11F_WARNED(status)) { - pe_debug("There were warnings while unpacking a Re-association Request (0x%08x, %d bytes):", - status, len); + hdr = (tpSirMacMgmtHdr)((uint8_t *)roam_synch + + roam_synch->reassoc_req_offset); + if (hdr->fc.type == SIR_MAC_MGMT_FRAME && + hdr->fc.subType == SIR_MAC_MGMT_ASSOC_REQ) { + ies_offset = WLAN_ASSOC_REQ_IES_OFFSET; + pe_debug("roam assoc req frm"); + } else { + pe_debug("roam reassoc req frm"); } + + if (roam_synch->reassoc_req_length < + (sizeof(tSirMacMgmtHdr) + ies_offset)) { + pe_err("invalid reassoc req len %d", + roam_synch->reassoc_req_length); + return; + } + qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, + (uint8_t *)roam_synch + + roam_synch->reassoc_req_offset, + roam_synch->reassoc_req_length); + ft_session->limRmfEnabled = false; - if (!assoc_req->RSNOpaque.present && !assoc_req->WPAOpaque.present) { - qdf_mem_free(assoc_req); + + assoc_ies = (uint8_t *)roam_synch + roam_synch->reassoc_req_offset + + sizeof(tSirMacMgmtHdr) + ies_offset; + assoc_ies_len = roam_synch->reassoc_req_length - + sizeof(tSirMacMgmtHdr) - ies_offset; + + rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, assoc_ies, + assoc_ies_len); + wpa_oui = WLAN_WPA_SEL(WLAN_WPA_OUI_TYPE); + wpa_ie = wlan_get_vendor_ie_ptr_from_oui((uint8_t *)&wpa_oui, + WLAN_OUI_SIZE, assoc_ies, + assoc_ies_len); + if (!wpa_ie && !rsn_ie) { + pe_nofl_debug("RSN and WPA IE not present"); return; } - if (assoc_req->RSNOpaque.present) { - rsn_ie.info[0] = WLAN_ELEMID_RSN; - rsn_ie.info[1] = assoc_req->RSNOpaque.num_data; - - rsn_ie.length = assoc_req->RSNOpaque.num_data + 2; - qdf_mem_copy(&rsn_ie.info[2], assoc_req->RSNOpaque.data, - assoc_req->RSNOpaque.num_data); - } else if (assoc_req->WPAOpaque.present) { - rsn_ie.info[0] = WLAN_ELEMID_VENDOR; - rsn_ie.info[1] = WLAN_OUI_SIZE + assoc_req->WPAOpaque.num_data; - - rsn_ie.length = WLAN_OUI_SIZE + - assoc_req->WPAOpaque.num_data + 2; - - qdf_mem_copy(&rsn_ie.info[2], (uint8_t *)&value, WLAN_OUI_SIZE); - qdf_mem_copy(&rsn_ie.info[WLAN_OUI_SIZE + 2], - assoc_req->WPAOpaque.data, - assoc_req->WPAOpaque.num_data); - } - - qdf_mem_free(assoc_req); - wlan_set_vdev_crypto_prarams_from_ie(ft_session->vdev, rsn_ie.info, - rsn_ie.length); - + wlan_set_vdev_crypto_prarams_from_ie(ft_session->vdev, assoc_ies, + assoc_ies_len); ft_session->limRmfEnabled = lim_get_vdev_rmf_capable(mac_ctx, ft_session); + crypto_params = wlan_crypto_vdev_get_crypto_params(ft_session->vdev); + if (!crypto_params) { + pe_err("crypto params is null"); + return; + } + pe_nofl_debug("vdev %d roam auth 0x%x akm 0x%0x rsn_caps 0x%x", + ft_session->vdev_id, + crypto_params->authmodeset, + crypto_params->key_mgmt, + crypto_params->rsn_caps); } #else -static inline void pe_set_rmf_caps(struct mac_context *mac_ctx, - struct pe_session *ft_session, - struct roam_offload_synch_ind *roam_synch) +static inline +void pe_update_crypto_params(struct mac_context *mac_ctx, + struct pe_session *ft_session, + struct roam_offload_synch_ind *roam_synch) { } #endif @@ -2624,7 +2630,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, /* Next routine will update nss and vdev_nss with AP's capabilities */ lim_fill_ft_session(mac_ctx, bss_desc, ft_session_ptr, session_ptr, roam_sync_ind_ptr->phy_mode); - pe_set_rmf_caps(mac_ctx, ft_session_ptr, roam_sync_ind_ptr); + pe_update_crypto_params(mac_ctx, ft_session_ptr, roam_sync_ind_ptr); /* Next routine may update nss based on dot11Mode */ lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc); if (session_ptr->is11Rconnection) diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c index 02d4ab9c28d5..262b4f292c30 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c @@ -10789,23 +10789,6 @@ csr_cm_roam_fill_11w_params(struct mac_context *mac_ctx, } } -#ifdef WLAN_FEATURE_ROAM_OFFLOAD -static void -csr_cm_roam_fill_rsn_caps(struct mac_context *mac, uint8_t vdev_id, - uint16_t *rsn_caps) -{ - tCsrRoamConnectedProfile *profile; - - /* Copy the self RSN capabilities in roam offload request */ - profile = &mac->roam.roamSession[vdev_id].connectedProfile; - *rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_ENABLED; - *rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED; - if (profile->MFPRequired) - *rsn_caps |= WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED; - if (profile->MFPCapable) - *rsn_caps |= WLAN_CRYPTO_RSN_CAP_MFP_ENABLED; -} -#endif #else static inline void csr_update_pmf_cap_from_profile(struct csr_roam_profile *profile, @@ -10817,13 +10800,6 @@ void csr_cm_roam_fill_11w_params(struct mac_context *mac_ctx, uint8_t vdev_id, struct ap_profile_params *req) {} - -#ifdef WLAN_FEATURE_ROAM_OFFLOAD -static inline -void csr_cm_roam_fill_rsn_caps(struct mac_context *mac, uint8_t vdev_id, - uint16_t *rsn_caps) -{} -#endif #endif QDF_STATUS csr_fill_filter_from_vdev_crypto(struct mac_context *mac_ctx, @@ -10846,7 +10822,7 @@ QDF_STATUS csr_fill_filter_from_vdev_crypto(struct mac_context *mac_ctx, filter->ucastcipherset = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER); filter->key_mgmt = - wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); + wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT); filter->mgmtcipherset = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER); @@ -17569,6 +17545,8 @@ static void csr_update_score_params(struct mac_context *mac_ctx, req_score_params->bw_weightage = weight_config->chan_width_weightage; req_score_params->band_weightage = weight_config->chan_band_weightage; req_score_params->nss_weightage = weight_config->nss_weightage; + req_score_params->security_weightage = + weight_config->security_weightage; req_score_params->esp_qbss_weightage = weight_config->channel_congestion_weightage; req_score_params->beamforming_weightage = @@ -17590,6 +17568,8 @@ static void csr_update_score_params(struct mac_context *mac_ctx, req_score_params->nss_index_score = score_config->nss_weight_per_index; + req_score_params->security_index_score = + score_config->security_weight_per_index; req_score_params->vendor_roam_score_algorithm = score_config->vendor_roam_score_algorithm; @@ -17991,7 +17971,9 @@ csr_cm_roam_fill_crypto_params(struct mac_context *mac_ctx, struct ap_profile *profile) { struct wlan_objmgr_vdev *vdev; - int32_t uccipher, authmode, mccipher, akm; + int32_t uccipher, authmode, mccipher, akm, key_mgmt; + int32_t num_allowed_authmode = 0; + enum wlan_crypto_key_mgmt i; vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, session->vdev_id, @@ -18015,6 +17997,25 @@ csr_cm_roam_fill_crypto_params(struct mac_context *mac_ctx, /* Group cipher suite */ profile->rsn_mcastcipherset = cm_crypto_cipher_wmi_cipher(mccipher); + + /* Get keymgmt from self security info */ + key_mgmt = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT); + + for (i = 0; i < WLAN_CRYPTO_KEY_MGMT_MAX; i++) { + /* + * Send AKM in allowed list which are not present in connected + * akm + */ + if (QDF_HAS_PARAM(key_mgmt, i) && + num_allowed_authmode < WLAN_CRYPTO_AUTH_MAX) { + profile->allowed_authmode[num_allowed_authmode++] = + cm_crypto_authmode_to_wmi_authmode(authmode, + (key_mgmt & (1 << i)), + uccipher); + } + } + + profile->num_allowed_authmode = num_allowed_authmode; } /** @@ -18604,6 +18605,8 @@ static QDF_STATUS csr_cm_roam_scan_offload_fill_lfr3_config( uint16_t rsn_caps = 0; tpCsrNeighborRoamControlInfo roam_info = &mac->roam.neighborRoamInfo[vdev_id]; + struct wlan_objmgr_vdev *vdev; + int32_t crypto_rsn = 0; rso_config->roam_offload_enabled = mac->mlme_cfg->lfr.lfr3_roaming_offload; @@ -18668,16 +18671,30 @@ static QDF_STATUS csr_cm_roam_scan_offload_fill_lfr3_config( (uint16_t)((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); final_caps_val = (uint16_t *)&self_caps; - /* - * Self rsn caps aren't sent to firmware, so in case of PMF required, - * the firmware connects to a non PMF AP advertising PMF not required - * in the re-assoc request which violates protocol. - * So send self RSN caps to firmware in roam SCAN offload command to - * let it configure the params in the re-assoc request too. - * Instead of making another infra, send the RSN-CAPS in MSB of - * beacon Caps. - */ - csr_cm_roam_fill_rsn_caps(mac, vdev_id, &rsn_caps); + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, + vdev_id, + WLAN_LEGACY_SME_ID); + if (vdev) { + /* + * Self rsn caps aren't sent to firmware, so in case of PMF + * required, the firmware connects to a non PMF AP advertising + * PMF not required in the re-assoc request which violates + * protocol. So send self RSN caps to firmware in roam SCAN + * offload command to let it configure the params in the + * re-assoc request too. Instead of making another infra, send + * the RSN-CAPS in MSB of beacon Caps. + */ + crypto_rsn = + wlan_crypto_get_param(vdev, + WLAN_CRYPTO_PARAM_ORIG_RSN_CAP); + if (crypto_rsn < 0) + sme_err("Invalid RSN capabilities"); + else + rsn_caps = (uint16_t)crypto_rsn; + + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + } + rso_config->rso_lfr3_caps.capability = (rsn_caps << RSN_CAPS_SHIFT) | ((*final_caps_val) & 0xFFFF); diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c index 8c08c6a19c57..0343476c116a 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-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 @@ -35,6 +35,7 @@ #include "wlan_reg_services_api.h" #include "wlan_crypto_global_api.h" #include "wlan_cm_roam_api.h" +#include "wlan_crypto_def_i.h" uint8_t csr_wpa_oui[][CSR_WPA_OUI_SIZE] = { {0x00, 0x50, 0xf2, 0x00} @@ -2445,6 +2446,127 @@ static inline void csr_update_pmksa_to_profile(struct csr_roam_profile *profile, } #endif +static void csr_update_key_mgmt_crypto_param(struct wlan_objmgr_vdev *vdev, + tDot11fIERSN ap_rsn) +{ + int32_t key_mgmt = 0; + int32_t neg_akm; + + neg_akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); + if (neg_akm < 0) { + sme_err("Invalid AKM suite"); + return; + } + + SET_PARAM(neg_akm, + wlan_crypto_rsn_suite_to_keymgmt(ap_rsn.akm_suite[0])); + + /* + * As there can be multiple AKM present select the most secured AKM + * present + */ + if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_SAE)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B); + else if (HAS_PARAM(neg_akm, + WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192)) + SET_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OWE)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_DPP)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_DPP); + else if (HAS_PARAM(neg_akm, + WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) + SET_PARAM(key_mgmt, + WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_CCKM); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OSEN)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OSEN); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPS)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPS); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA); + else if (HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPA_NONE)) + SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPA_NONE); + else /* use original if no akm match */ + key_mgmt = neg_akm; + + wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, + key_mgmt); +} + +static void csr_update_ucast_cipher_crypto_param(struct wlan_objmgr_vdev *vdev, + tDot11fIERSN ap_rsn) +{ + int32_t ucastcipherset = 0; + int32_t neg_ucastcipher; + + neg_ucastcipher = wlan_crypto_get_param(vdev, + WLAN_CRYPTO_PARAM_UCAST_CIPHER); + if (neg_ucastcipher < 0) { + sme_err("Invalid unicast cipherset"); + return; + } + + SET_PARAM(neg_ucastcipher, + wlan_crypto_rsn_suite_to_cipher(ap_rsn.pwise_cipher_suites[0])); + + /* + * As there can be multiple ucastcipher present select the most secured + * ucastcipher present. + */ + if (HAS_PARAM(neg_ucastcipher, WLAN_CRYPTO_CIPHER_AES_GCM_256)) + SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM_256); + else if (HAS_PARAM(neg_ucastcipher, WLAN_CRYPTO_CIPHER_AES_CCM_256)) + SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM_256); + else if (HAS_PARAM(neg_ucastcipher, WLAN_CRYPTO_CIPHER_AES_GCM)) + SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM); + else if (HAS_PARAM(neg_ucastcipher, WLAN_CRYPTO_CIPHER_AES_CCM)) + SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM); + else if (HAS_PARAM(neg_ucastcipher, WLAN_CRYPTO_CIPHER_TKIP)) + SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_TKIP); + else + ucastcipherset = neg_ucastcipher; + + wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER, + ucastcipherset); +} + +#define MGMT_FRAME_FULL_PROTECTION (RSN_CAP_MFP_REQUIRED | RSN_CAP_MFP_CAPABLE) + uint8_t csr_construct_rsn_ie(struct mac_context *mac, uint32_t sessionId, struct csr_roam_profile *pProfile, struct bss_description *pSirBssDesc, @@ -2455,8 +2577,8 @@ uint8_t csr_construct_rsn_ie(struct mac_context *mac, uint32_t sessionId, uint8_t *rsn_ie = (uint8_t *)pRSNIe; uint8_t ie_len = 0; tDot11fBeaconIEs *local_ap_ie = ap_ie; - uint16_t rsn_cap = 0, self_rsn_cap; - int32_t rsn_val; + uint16_t rsn_cap = 0, self_rsn_cap, orig_rsn_cap; + int32_t rsn_val, orig_rsn_val; struct wlan_crypto_pmksa pmksa, *pmksa_peer; struct csr_roam_session *session = &mac->roam.roamSession[sessionId]; @@ -2500,6 +2622,33 @@ uint8_t csr_construct_rsn_ie(struct mac_context *mac, uint32_t sessionId, } wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP, self_rsn_cap); + + /* + * This user configure MFP capability is global and is for + * multiple profiles which can be used by firmware for cross-AKM + * roaming. When user configures MFP required then we should + * set both MFPC and MFPR in RSN caps. + */ + orig_rsn_val = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_ORIG_RSN_CAP); + if (orig_rsn_val < 0) { + sme_err("Invalid mgmt cipher"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + return ie_len; + } + orig_rsn_cap = (uint16_t)orig_rsn_val; + + if (orig_rsn_cap == RSN_CAP_MFP_REQUIRED) + orig_rsn_cap = MGMT_FRAME_FULL_PROTECTION; + + self_rsn_cap = (uint16_t)rsn_val; + self_rsn_cap = (self_rsn_cap) & (~MGMT_FRAME_FULL_PROTECTION); + orig_rsn_cap = self_rsn_cap | orig_rsn_cap; + wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_ORIG_RSN_CAP, + orig_rsn_cap); + + csr_update_key_mgmt_crypto_param(vdev, local_ap_ie->RSN); + csr_update_ucast_cipher_crypto_param(vdev, local_ap_ie->RSN); + qdf_mem_zero(&pmksa, sizeof(pmksa)); if (pSirBssDesc->fils_info_element.is_cache_id_present) { pmksa.ssid_len =