diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index 6a94ded4ad7b..deb0babfce0e 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -1690,6 +1690,7 @@ static void mlme_init_lfr_cfg(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_ROAM_INACTIVE_COUNT); lfr->roam_scan_period_after_inactivity = cfg_get(psoc, CFG_POST_INACTIVITY_ROAM_SCAN_PERIOD); + lfr->fw_akm_bitmap = 0; mlme_init_roam_offload_cfg(psoc, lfr); mlme_init_ese_cfg(psoc, lfr); diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index e1b2b9209252..802f73eb9c87 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1267,6 +1267,14 @@ struct bss_load_trigger { int32_t rssi_threshold_24ghz; }; +/* + * AKM suites supported by firmware for + * roaming + */ +#define AKM_FT_SAE 0 +#define AKM_FT_SUITEB_SHA384 1 +#define AKM_FT_FILS 2 + /* * @mawc_roam_enabled: Enable/Disable MAWC during roaming * @enable_fast_roam_in_concurrency:Enable LFR roaming on STA during concurrency @@ -1362,6 +1370,7 @@ struct bss_load_trigger { * during roam_scan_inactivity_time. * @roam_scan_period_after_inactivity: Roam scan period after device was in * inactive state + * @fw_akm_bitmap: Supported Akm suites of firmware */ struct wlan_mlme_lfr_cfg { bool mawc_roam_enabled; @@ -1459,6 +1468,7 @@ struct wlan_mlme_lfr_cfg { uint32_t roam_scan_inactivity_time; uint32_t roam_inactive_data_packet_count; uint32_t roam_scan_period_after_inactivity; + uint32_t fw_akm_bitmap; }; /** diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 4061029fccef..8dc5bf104be9 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -1079,6 +1079,7 @@ ucfg_mlme_set_roaming_offload(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } #endif + /** * ucfg_mlme_get_first_scan_bucket_threshold() - Get first scan bucket thre * @psoc: pointer to psoc object @@ -1090,6 +1091,18 @@ QDF_STATUS ucfg_mlme_get_first_scan_bucket_threshold(struct wlan_objmgr_psoc *psoc, uint8_t *val); +/** + * ucfg_mlme_set_fw_supported_roaming_akm() - update the supported roaming + * akm suites advertised by the firmware via wmi service capability + * @psoc: pointer to psoc object + * @val: bitmap value based on firmware capabilities + * + * Return: QDF Status + */ +QDF_STATUS +ucfg_mlme_set_fw_supported_roaming_akm(struct wlan_objmgr_psoc *psoc, + uint32_t val); + /** * ucfg_mlme_is_mawc_enabled() - MAWC enabled or not * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c index d1caa86e8162..3e33d846f9b6 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c @@ -774,6 +774,20 @@ ucfg_mlme_get_first_scan_bucket_threshold(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +QDF_STATUS +ucfg_mlme_set_fw_supported_roaming_akm(struct wlan_objmgr_psoc *psoc, + uint32_t val) +{ + struct wlan_mlme_psoc_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_INVAL; + + mlme_obj->cfg.lfr.fw_akm_bitmap = val; + return QDF_STATUS_SUCCESS; +} + QDF_STATUS ucfg_mlme_is_mawc_enabled(struct wlan_objmgr_psoc *psoc, bool *val) { diff --git a/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h index 9112d466640e..4f7795c17d42 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -32,7 +32,7 @@ #define PMO_GTK_OFFLOAD_DISABLE 1 #define PMO_KEK_LEN_LEGACY 16 #define PMO_KEK_LEN 64 -#define PMO_KCK_LEN 16 +#define PMO_KCK_LEN 32 #define PMO_REPLAY_COUNTER_LEN 8 #define PMO_MAC_MAX_KEY_LENGTH 32 #define PMO_IGTK_PN_SIZE 6 @@ -41,6 +41,7 @@ * struct pmo_gtk_req - pmo gtk request * @flags: optional flags * @kck: Key confirmation key + * @kck_len: Key confirmation key length * @kek: key encryption key * @kek_len: KEK Length * @replay_counter: replay_counter @@ -50,6 +51,7 @@ struct pmo_gtk_req { uint32_t flags; uint8_t kck[PMO_KCK_LEN]; + uint8_t kck_len; uint8_t kek[PMO_KEK_LEN]; uint32_t kek_len; uint64_t replay_counter; diff --git a/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c b/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c index 18132ea905f7..d88c60b3745e 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c +++ b/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -63,9 +63,9 @@ QDF_STATUS pmo_tgt_send_gtk_offload_req(struct wlan_objmgr_vdev *vdev, if (gtk_req->flags == PMO_GTK_OFFLOAD_ENABLE) { qdf_atomic_set(&vdev_ctx->gtk_err_enable, true); qdf_mem_copy(op_gtk_req->kck, gtk_req->kck, - PMO_KCK_LEN); + gtk_req->kck_len); qdf_mem_copy(op_gtk_req->kek, gtk_req->kek, - PMO_KEK_LEN); + PMO_KEK_LEN); qdf_mem_copy(&op_gtk_req->replay_counter, >k_req->replay_counter, PMO_REPLAY_COUNTER_LEN); } else { diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 5d980cb6a4eb..5bfceeeae59d 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2242,7 +2242,7 @@ void hdd_save_gtk_params(struct hdd_adapter *adapter, kek_len = csr_roam_info->fils_join_rsp->kek_len; } - wlan_hdd_save_gtk_offload_params(adapter, NULL, kek, kek_len, + wlan_hdd_save_gtk_offload_params(adapter, NULL, 0, kek, kek_len, csr_roam_info->replay_ctr, true); hdd_debug("Kek len %d", kek_len); @@ -2261,7 +2261,7 @@ void hdd_save_gtk_params(struct hdd_adapter *adapter, kek = csr_roam_info->kek; kek_len = csr_roam_info->kek_len; - wlan_hdd_save_gtk_offload_params(adapter, NULL, kek, kek_len, + wlan_hdd_save_gtk_offload_params(adapter, NULL, 0, kek, kek_len, csr_roam_info->replay_ctr, true); hdd_debug("Kek len %d", kek_len); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 0a8df1b12f5c..0f0676ff9a45 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4943,9 +4943,9 @@ wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, #ifdef WLAN_FEATURE_GTK_OFFLOAD void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, - uint8_t *kck_ptr, uint8_t *kek_ptr, - uint32_t kek_len, uint8_t *replay_ctr, - bool big_endian) + uint8_t *kck_ptr, uint8_t kck_len, + uint8_t *kek_ptr, uint32_t kek_len, + uint8_t *replay_ctr, bool big_endian) { struct hdd_station_ctx *hdd_sta_ctx; uint8_t *buf; @@ -4959,8 +4959,13 @@ void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, return; hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - if (kck_ptr) - qdf_mem_copy(gtk_req->kck, kck_ptr, NL80211_KCK_LEN); + if (kck_ptr) { + if (kck_len > sizeof(gtk_req->kck)) { + kck_len = sizeof(gtk_req->kck); + QDF_ASSERT(0); + } + qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len); + } if (kek_ptr) { /* paranoia */ @@ -4992,15 +4997,6 @@ void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, end: qdf_mem_free(gtk_req); } -#else -void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, - uint8_t *kck_ptr, - uint8_t *kek_ptr, - uint32_t kek_len, - uint8_t *replay_ctr, - bool big_endian) -{ -} #endif #if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) @@ -5160,7 +5156,7 @@ int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid, if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, - SIR_KCK_KEY_LEN, roam_info_ptr->kck) || + roam_info_ptr->kck_len, roam_info_ptr->kck) || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, roam_info_ptr->kek_len, roam_info_ptr->kek)) { @@ -5180,6 +5176,7 @@ int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid, * into power save state. */ wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck, + roam_info_ptr->kck_len, roam_info_ptr->kek, roam_info_ptr->kek_len, roam_info_ptr->replay_ctr, @@ -17120,10 +17117,19 @@ static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt) sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X; break; + case WLAN_AKM_SUITE_FT_SAE: + hdd_debug("setting key mgmt type to FT-SAE"); + sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X; + break; + + case WLAN_AKM_SUITE_FT_EAP_SHA_384: + hdd_debug("setting key mgmt type to FT-EAP-SHA384"); + sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X; + break; + default: hdd_err("Unsupported key mgmt type: %d", key_mgmt); return -EINVAL; - } return 0; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 1addfc7d225a..183055cf4736 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -112,6 +112,14 @@ struct hdd_context; #define WLAN_AKM_SUITE_SAE 0x000FAC08 #endif +#ifndef WLAN_AKM_SUITE_FT_SAE +#define WLAN_AKM_SUITE_FT_SAE 0x000FAC09 +#endif + +#ifndef WLAN_AKM_SUITE_FT_EAP_SHA_384 +#define WLAN_AKM_SUITE_FT_EAP_SHA_384 0x000FAC0D +#endif + #ifdef FEATURE_WLAN_TDLS #define WLAN_IS_TDLS_SETUP_ACTION(action) \ ((SIR_MAC_TDLS_SETUP_REQ <= action) && \ @@ -579,11 +587,13 @@ int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList, */ void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity); +#ifdef WLAN_FEATURE_GTK_OFFLOAD /** * wlan_hdd_save_gtk_offload_params() - Save gtk offload parameters in STA * context for offload operations. * @adapter: Adapter context * @kck_ptr: KCK buffer pointer + * @kck_len: KCK length * @kek_ptr: KEK buffer pointer * @kek_len: KEK length * @replay_ctr: Pointer to 64 bit long replay counter @@ -592,11 +602,17 @@ void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity); * Return: None */ void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, - uint8_t *kck_ptr, - uint8_t *kek_ptr, - uint32_t kek_len, - uint8_t *replay_ctr, - bool big_endian); + uint8_t *kck_ptr, uint8_t kck_len, + uint8_t *kek_ptr, uint32_t kek_len, + uint8_t *replay_ctr, bool big_endian); +#else +void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, + uint8_t *kck_ptr, uint8_t kck_len, + uint8_t *kek_ptr, uint32_t kek_len, + uint8_t *replay_ctr, bool big_endian) +{} +#endif + /** * wlan_hdd_flush_pmksa_cache() - flush pmksa cache for adapter diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index b7d29f37b790..c2a17b59bb80 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1945,6 +1945,12 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) hdd_lpass_target_config(hdd_ctx, cfg); hdd_ctx->ap_arpns_support = cfg->ap_arpns_support; + status = ucfg_mlme_set_fw_supported_roaming_akm( + hdd_ctx->psoc, + cfg->ft_akm_service_bitmap); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to set ft akm suites bitmap"); + hdd_update_tgt_services(hdd_ctx, &cfg->services); hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c379b5957d8d..fa1e81beb07b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -112,8 +112,13 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN]; #define SIR_KRK_KEY_LEN 16 #define SIR_BTK_KEY_LEN 32 #define SIR_KCK_KEY_LEN 16 +#define KCK_192BIT_KEY_LEN 24 +#define KCK_256BIT_KEY_LEN 32 + #define SIR_KEK_KEY_LEN 16 #define SIR_KEK_KEY_LEN_FILS 64 +#define KEK_256BIT_KEY_LEN 32 + #define SIR_REPLAY_CTR_LEN 8 #define SIR_PMK_LEN 48 #ifdef WLAN_FEATURE_ROAM_OFFLOAD @@ -3000,7 +3005,8 @@ struct roam_offload_synch_ind { uint8_t rssi; uint8_t roamReason; uint32_t chan_freq; - uint8_t kck[SIR_KCK_KEY_LEN]; + uint8_t kck[KCK_256BIT_KEY_LEN]; + uint8_t kck_len; uint32_t kek_len; uint8_t kek[SIR_KEK_KEY_LEN_FILS]; uint32_t pmk_len; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 16439280029e..72e1196b3d00 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1129,7 +1129,8 @@ struct csr_roam_info { #ifdef WLAN_FEATURE_ROAM_OFFLOAD uint8_t roamSynchInProgress; uint8_t synchAuthStatus; - uint8_t kck[SIR_KCK_KEY_LEN]; + uint8_t kck[KCK_256BIT_KEY_LEN]; + uint8_t kck_len; uint8_t kek[SIR_KEK_KEY_LEN_FILS]; uint8_t kek_len; uint32_t pmk_len; @@ -1384,10 +1385,38 @@ typedef QDF_STATUS (*csr_session_close_cb)(uint8_t session_id); #ifdef WLAN_FEATURE_SAE #define CSR_IS_AUTH_TYPE_SAE(auth_type) \ (eCSR_AUTH_TYPE_SAE == auth_type) + +#define CSR_IS_AKM_FT_SAE(auth_type) \ + (eCSR_AUTH_TYPE_FT_SAE == (auth_type)) + +#define CSR_IS_FW_FT_SAE_SUPPORTED(fw_akm_bitmap) \ + (((fw_akm_bitmap) & (1 << AKM_FT_SAE)) ? true : false) + #else #define CSR_IS_AUTH_TYPE_SAE(auth_type) (false) + +#define CSR_IS_AKM_FT_SAE(auth_type) (false) + +#define CSR_IS_FW_FT_SAE_SUPPORTED(fw_akm_bitmap) (false) #endif +#define CSR_IS_AKM_FT_SUITEB_SHA384(auth_type) \ + (eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 == (auth_type)) + +#define CSR_IS_AKM_FILS(auth_type) \ + ((eCSR_AUTH_TYPE_FILS_SHA256 == auth_type) || \ + (eCSR_AUTH_TYPE_FILS_SHA384 == auth_type)) + +#define CSR_IS_AKM_FT_FILS(auth_type) \ + ((eCSR_AUTH_TYPE_FT_FILS_SHA256 == (auth_type)) || \ + (eCSR_AUTH_TYPE_FT_FILS_SHA384 == (auth_type))) + +#define CSR_IS_FW_FT_SUITEB_SUPPORTED(fw_akm_bitmap) \ + (((fw_akm_bitmap) & (1 << AKM_FT_SUITEB_SHA384)) ? true : false) + +#define CSR_IS_FW_FT_FILS_SUPPORTED(fw_akm_bitmap) \ + (((fw_akm_bitmap) & (1 << AKM_FT_FILS)) ? true : false) + QDF_STATUS csr_set_channels(struct mac_context *mac, struct csr_config_params *pParam); diff --git a/core/sme/inc/csr_support.h b/core/sme/inc/csr_support.h index 53be875aa808..d7346ea89045 100644 --- a/core/sme/inc/csr_support.h +++ b/core/sme/inc/csr_support.h @@ -39,7 +39,7 @@ #define CSR_RSN_OUI_SIZE (4) #define CSR_RSN_VERSION_SUPPORTED (1) -#define CSR_RSN_MAX_AUTH_SUITES (4) +#define CSR_RSN_MAX_AUTH_SUITES (5) #define CSR_RSN_MAX_CYPHERS (5) #define CSR_RSN_MAX_UNICAST_CYPHERS (5) #define CSR_RSN_MAX_MULTICAST_CYPHERS (1) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 34a5bd083ed1..4bfeddf370a7 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14416,6 +14416,38 @@ csr_roam_diag_set_pmkid(struct csr_roam_session *pSession) } #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * csr_update_session_psk_pmk - API to update PMK in csr session + * @pSession: pointer to session + * @pmksa: pointer to PMKSA struct + * + * Return : None + */ +static void +csr_update_session_psk_pmk(struct csr_roam_session *session, + tPmkidCacheInfo *pmksa) +{ + /* For SAE authentication, pmk will be sent over the + * set PMKSA vendor command. The set PMKSA command is sent + * after SAE authentication is complete, before association + * completion itself. So csr_roam_session will not be having + * any parameters at this point. This pmk received is not + * updated to csr session and when RSO update command is sent, + * empty pmk will be sent, resulting in SAE roming failure. So + * copy the pmk into csr session so that correct pmk will be + * sent in RSO command. + */ + qdf_mem_copy(session->psk_pmk, pmksa->pmk, pmksa->pmk_len); + session->pmk_len = pmksa->pmk_len; +} +#else +static inline void +csr_update_session_psk_pmk(struct csr_roam_session *session, + tPmkidCacheInfo *pmksa) +{} +#endif + /** * csr_update_pmk_cache - API to update PMK cache * @pSession: pointer to session @@ -14447,9 +14479,12 @@ static void csr_update_pmk_cache(struct csr_roam_session *session, session->PmkidCacheInfo[cache_idx].PMKID, pmksa->PMKID, PMKID_LEN); - if (pmksa->pmk_len) + if (pmksa->pmk_len) { qdf_mem_copy(session->PmkidCacheInfo[cache_idx].pmk, - pmksa->pmk, pmksa->pmk_len); + pmksa->pmk, pmksa->pmk_len); + + csr_update_session_psk_pmk(session, pmksa); + } session->PmkidCacheInfo[cache_idx].pmk_len = pmksa->pmk_len; @@ -19409,6 +19444,8 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id, uint8_t i, temp_session_id; uint8_t op_channel; bool prev_roaming_state; + eCsrAuthType roam_profile_akm = eCSR_AUTH_TYPE_UNKNOWN; + uint32_t fw_akm_bitmap; sme_debug("RSO Command %d, Session id %d, Reason %d", command, session_id, reason); @@ -19467,30 +19504,56 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id, return QDF_STATUS_E_FAILURE; } - /* Roaming is not supported currently for FILS akm */ - if (session->pCurRoamProfile && CSR_IS_AUTH_TYPE_FILS( - session->pCurRoamProfile->AuthType.authType[0]) && + if (session->pCurRoamProfile) + roam_profile_akm = + session->pCurRoamProfile->AuthType.authType[0]; + else + sme_info("Roam profile is NULL"); + + if (CSR_IS_AKM_FILS(roam_profile_akm) && !mac_ctx->is_fils_roaming_supported) { sme_info("FILS Roaming not suppprted by fw"); return QDF_STATUS_SUCCESS; } /* Roaming is not supported currently for OWE akm */ - if (session->pCurRoamProfile && - (session->pCurRoamProfile->AuthType.authType[0] == - eCSR_AUTH_TYPE_OWE)) { + if (roam_profile_akm == eCSR_AUTH_TYPE_OWE) { sme_info("OWE Roaming not suppprted by fw"); return QDF_STATUS_SUCCESS; } - /* Roaming is not supported currently for SAE authentication */ - if (session->pCurRoamProfile && - CSR_IS_AUTH_TYPE_SAE( - session->pCurRoamProfile->AuthType.authType[0])) { + /* Roaming is not supported for SAE authentication */ + if (CSR_IS_AUTH_TYPE_SAE(roam_profile_akm)) { sme_info("Roaming not suppprted for SAE connection"); return QDF_STATUS_SUCCESS; } + /* + * If fw doesn't advertise FT SAE, FT-FILS or FT-Suite-B capability, + * don't support roaming to that profile + */ + fw_akm_bitmap = mac_ctx->mlme_cfg->lfr.fw_akm_bitmap; + if (CSR_IS_AKM_FT_SAE(roam_profile_akm)) { + if (!CSR_IS_FW_FT_SAE_SUPPORTED(fw_akm_bitmap)) { + sme_info("Roaming not suppprted for FT SAE akm"); + return QDF_STATUS_SUCCESS; + } + } + + if (CSR_IS_AKM_FT_SUITEB_SHA384(roam_profile_akm)) { + if (!CSR_IS_FW_FT_SUITEB_SUPPORTED(fw_akm_bitmap)) { + sme_info("Roaming not suppprted for FT Suite-B akm"); + return QDF_STATUS_SUCCESS; + } + } + + if (CSR_IS_AKM_FT_FILS(roam_profile_akm)) { + if (!CSR_IS_FW_FT_FILS_SUPPORTED(fw_akm_bitmap)) { + sme_info("Roaming not suppprted for FT FILS akm"); + return QDF_STATUS_SUCCESS; + } + } + /* * The Dynamic Config Items Update may happen even if the state is in * INIT. It is important to ensure that the command is passed down to @@ -21760,9 +21823,10 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, } roam_info->roamSynchInProgress = true; roam_info->synchAuthStatus = roam_synch_data->authStatus; + roam_info->kck_len = roam_synch_data->kck_len; roam_info->kek_len = roam_synch_data->kek_len; roam_info->pmk_len = roam_synch_data->pmk_len; - qdf_mem_copy(roam_info->kck, roam_synch_data->kck, SIR_KCK_KEY_LEN); + qdf_mem_copy(roam_info->kck, roam_synch_data->kck, roam_info->kck_len); qdf_mem_copy(roam_info->kek, roam_synch_data->kek, roam_info->kek_len); if (roam_synch_data->pmk_len) diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index dd1cd2ca7e46..7f903d9f1b83 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -2991,11 +2991,29 @@ static bool csr_is_auth_wpa_sae(struct mac_context *mac, bool is_sae_auth; is_sae_auth = (csr_is_oui_match(mac, all_suites, suite_count, - csr_rsn_oui[ENUM_SAE], oui) || - csr_is_oui_match(mac, all_suites, suite_count, - csr_rsn_oui[ENUM_FT_SAE], oui)); + csr_rsn_oui[ENUM_SAE], oui)); return is_sae_auth; } + +/* + * csr_is_auth_ft_sae() - check whether oui is SAE + * @mac: Global MAC context + * @all_suites: pointer to all supported akm suites + * @suite_count: all supported akm suites count + * @oui: Oui needs to be matched + * + * Return: True if OUI is FT-SAE, false otherwise + */ +static bool csr_is_auth_ft_sae(struct mac_context *mac, + uint8_t all_suites[][CSR_RSN_OUI_SIZE], + uint8_t suite_count, uint8_t oui[]) +{ + bool is_ft_sae_auth; + + is_ft_sae_auth = csr_is_oui_match(mac, all_suites, suite_count, + csr_rsn_oui[ENUM_FT_SAE], oui); + return is_ft_sae_auth; +} #endif /* @@ -3170,7 +3188,8 @@ static void csr_is_fils_auth(struct mac_context *mac_ctx, #ifdef WLAN_FEATURE_SAE /** - * csr_check_sae_auth() - update negotiated auth if matches to SAE auth type + * csr_check_sae_auth() - update negotiated auth and oui if matches to SAE auth + * type * @mac_ctx: pointer to mac context * @authsuites: auth suites * @c_auth_suites: auth suites count @@ -3181,18 +3200,25 @@ static void csr_is_fils_auth(struct mac_context *mac_ctx, * * Return: None */ -static void csr_check_sae_auth(struct mac_context *mac_ctx, - uint8_t authsuites[][CSR_RSN_OUI_SIZE], uint8_t c_auth_suites, - uint8_t authentication[], tCsrAuthList *auth_type, - uint8_t index, eCsrAuthType *neg_authtype) +static void +csr_check_sae_auth(struct mac_context *mac_ctx, + uint8_t authsuites[][CSR_RSN_OUI_SIZE], + uint8_t c_auth_suites, + uint8_t authentication[], tCsrAuthList *auth_type, + uint8_t index, eCsrAuthType *neg_authtype) { if ((*neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) && - csr_is_auth_wpa_sae(mac_ctx, authsuites, - c_auth_suites, authentication)) { + csr_is_auth_ft_sae(mac_ctx, authsuites, c_auth_suites, + authentication)) { + if (eCSR_AUTH_TYPE_FT_SAE == auth_type->authType[index]) + *neg_authtype = eCSR_AUTH_TYPE_FT_SAE; + } + + if ((*neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) && + csr_is_auth_wpa_sae(mac_ctx, authsuites, + c_auth_suites, authentication)) { if (eCSR_AUTH_TYPE_SAE == auth_type->authType[index]) *neg_authtype = eCSR_AUTH_TYPE_SAE; - else if (eCSR_AUTH_TYPE_FT_SAE == auth_type->authType[index]) - *neg_authtype = eCSR_AUTH_TYPE_FT_SAE; } sme_debug("negotiated auth type is %d", *neg_authtype); } diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index b7ddd9933d7d..d3ae9562df50 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -173,6 +173,7 @@ struct board_info { * @obss_color_collision_offloaded: obss color collision offloaded to firmware * @sar_version: Version of SAR supported by firmware * @bcast_twt_support: braodcast twt support + * @ft_akm_service_bitmap: bitmap of FT akm supported by firmware */ struct wma_tgt_cfg { uint32_t target_fw_version; @@ -213,5 +214,6 @@ struct wma_tgt_cfg { enum sar_version sar_version; struct nan_tgt_caps nan_caps; bool bcast_twt_support; + uint32_t ft_akm_service_bitmap; }; #endif /* WMA_TGT_CFG_H */ diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 0bfafadfdd9f..458f84eb3a17 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5646,6 +5646,16 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) tgt_cfg.max_intf_count = wlan_res_cfg->num_vdevs; + if (wmi_service_enabled(wmi_handle, wmi_service_wpa3_ft_sae_support)) + tgt_cfg.ft_akm_service_bitmap |= (1 << AKM_FT_SAE); + + if (wmi_service_enabled(wmi_handle, + wmi_service_wpa3_ft_suite_b_support)) + tgt_cfg.ft_akm_service_bitmap |= (1 << AKM_FT_SUITEB_SHA384); + + if (wmi_service_enabled(wmi_handle, wmi_service_ft_fils)) + tgt_cfg.ft_akm_service_bitmap |= (1 << AKM_FT_FILS); + qdf_mem_copy(tgt_cfg.hw_macaddr.bytes, wma_handle->hwaddr, ATH_MAC_LEN); diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 695ffa068fdf..58b5c61cd5a4 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -306,7 +306,7 @@ static void wma_roam_scan_offload_set_params( qdf_mem_copy(params->krk, roam_req->KRK, WMI_KRK_KEY_LEN); qdf_mem_copy(params->btk, roam_req->BTK, WMI_BTK_KEY_LEN); qdf_mem_copy(params->psk_pmk, roam_req->PSK_PMK, - WMI_ROAM_SCAN_PSK_SIZE); + roam_req->pmk_len); params->pmk_len = roam_req->pmk_len; params->roam_key_mgmt_offload_enabled = roam_req->RoamKeyMgmtOffloadEnabled; @@ -762,10 +762,18 @@ A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype, return WMI_AUTH_RSNA_FILS_SHA256; case eCSR_AUTH_TYPE_FILS_SHA384: return WMI_AUTH_RSNA_FILS_SHA384; + case eCSR_AUTH_TYPE_FT_FILS_SHA256: + return WMI_AUTH_FT_RSNA_FILS_SHA256; + case eCSR_AUTH_TYPE_FT_FILS_SHA384: + return WMI_AUTH_FT_RSNA_FILS_SHA384; case eCSR_AUTH_TYPE_SUITEB_EAP_SHA256: return WMI_AUTH_RSNA_SUITE_B_8021X_SHA256; case eCSR_AUTH_TYPE_SUITEB_EAP_SHA384: return WMI_AUTH_RSNA_SUITE_B_8021X_SHA384; + case eCSR_AUTH_TYPE_FT_SAE: + return WMI_AUTH_FT_RSNA_SAE; + case eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384: + return WMI_AUTH_FT_RSNA_SUITE_B_8021X_SHA384; default: return WMI_AUTH_NONE; } @@ -2306,9 +2314,12 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, wmi_roam_synch_event_fixed_param *synch_event; wmi_channel *chan; wmi_key_material *key; + wmi_key_material_ext *key_ft; struct wma_txrx_node *iface = NULL; wmi_roam_fils_synch_tlv_param *fils_info; int status = -EINVAL; + uint8_t kck_len; + uint8_t kek_len; synch_event = param_buf->fixed_param; roam_synch_ind_ptr->roamed_vdev_id = synch_event->vdev_id; @@ -2368,8 +2379,11 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, chan = param_buf->chan; if (chan) roam_synch_ind_ptr->chan_freq = chan->mhz; + key = param_buf->key; + key_ft = param_buf->key_ext; if (key) { + roam_synch_ind_ptr->kck_len = SIR_KCK_KEY_LEN; qdf_mem_copy(roam_synch_ind_ptr->kck, key->kck, SIR_KCK_KEY_LEN); roam_synch_ind_ptr->kek_len = SIR_KEK_KEY_LEN; @@ -2377,7 +2391,32 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, SIR_KEK_KEY_LEN); qdf_mem_copy(roam_synch_ind_ptr->replay_ctr, key->replay_counter, SIR_REPLAY_CTR_LEN); + } else if (key_ft) { + /* + * For AKM 00:0F:AC (FT suite-B-SHA384) + * KCK-bits:192 KEK-bits:256 + * Firmware sends wmi_key_material_ext tlv now only if + * auth is FT Suite-B SHA-384 auth. If further new suites + * are added, add logic to get kck, kek bits based on + * akm protocol + */ + kck_len = KCK_192BIT_KEY_LEN; + kek_len = KEK_256BIT_KEY_LEN; + + roam_synch_ind_ptr->kek_len = kek_len; + qdf_mem_copy(roam_synch_ind_ptr->kek, + key_ft->key_buffer, kek_len); + + roam_synch_ind_ptr->kck_len = kck_len; + qdf_mem_copy(roam_synch_ind_ptr->kck, + (key_ft->key_buffer + kek_len), + kck_len); + + qdf_mem_copy(roam_synch_ind_ptr->replay_ctr, + (key_ft->key_buffer + kek_len + kck_len), + SIR_REPLAY_CTR_LEN); } + if (param_buf->hw_mode_transition_fixed_param) wma_process_pdev_hw_mode_trans_ind(wma, param_buf->hw_mode_transition_fixed_param,