diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 536390aec461..8531cf162dc0 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/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) @@ -17808,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); } /** @@ -21057,6 +21070,19 @@ hdd_populate_crypto_cipher_type(struct wlan_objmgr_vdev *vdev, } } +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; + } +} + /** * hdd_populate_crypto_params() - set crypto params * @vdev: Pointer to vdev obh mgr @@ -21103,6 +21129,25 @@ static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev, 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); wlan_crypto_free_vdev_key(vdev); } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index d0a1d23c0fd2..262b4f292c30 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10822,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); @@ -18684,8 +18684,9 @@ static QDF_STATUS csr_cm_roam_scan_offload_fill_lfr3_config( * 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_RSN_CAP); + crypto_rsn = + wlan_crypto_get_param(vdev, + WLAN_CRYPTO_PARAM_ORIG_RSN_CAP); if (crypto_rsn < 0) sme_err("Invalid RSN capabilities"); else diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 3ecb634f3889..0343476c116a 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -2565,6 +2565,8 @@ static void csr_update_ucast_cipher_crypto_param(struct wlan_objmgr_vdev *vdev, 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, @@ -2575,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]; @@ -2621,6 +2623,29 @@ 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);