diff options
| author | Sridhar Selvaraj <sselvara@codeaurora.org> | 2017-08-07 16:43:30 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-08-16 21:44:19 -0700 |
| commit | 5d51228bcaa931c377fe1300dc9cc9710b68bf20 (patch) | |
| tree | 83490d7c000864f97aa7f6d421a6a83f316eb2c0 | |
| parent | 7d3a7a22e0a3ac2e9dd20cef7854f30b2b2a7544 (diff) | |
qcacld-3.0: Add FILS roaming support
Add FILS roaming support changes as follows:
- Update ERP info in RSO Start
- Update HLP info in a new command WMI_PDEV_UPDATE_FILS_HLP_PKT_CMDID
- Set/Delete PMK cache info with WMI_PDEV_UPDATE_PMK_CACHE_CMDID
- Process FILS TLV in Roam Synch Indication and update the FILS info
[seq number,PMK, KEK, realm] to Supplicant.
Change-Id: I78c3bdde080701deb8d2bdb92d8d57d18cceb864
CRs-Fixed: 2081252
28 files changed, 1350 insertions, 167 deletions
diff --git a/core/cds/inc/cds_config.h b/core/cds/inc/cds_config.h index ee28d92a1292..4553eb0fada2 100644 --- a/core/cds/inc/cds_config.h +++ b/core/cds/inc/cds_config.h @@ -172,9 +172,11 @@ struct cds_config_info { #ifdef WLAN_FEATURE_FILS_SK #define MAX_PMK_LEN 48 +#define MAX_PMKID_LEN 16 #define FILS_MAX_KEYNAME_NAI_LENGTH 255 #define FILS_MAX_REALM_LEN 255 #define FILS_MAX_RRK_LENGTH 64 +#define FILS_MAX_RIK_LENGTH FILS_MAX_RRK_LENGTH struct cds_fils_connection_info { bool is_fils_connection; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 12ac9f670360..a418f7b71ba2 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2688,4 +2688,21 @@ void hdd_dp_trace_init(struct hdd_config *config); int hdd_set_limit_off_chan_for_tos(hdd_adapter_t *adapter, enum tos tos, bool is_tos_active); +#if defined(WLAN_FEATURE_FILS_SK) +/** + * hdd_update_hlp_info() - Update HLP packet received in FILS (re)assoc rsp + * @dev: net device + * @roam_fils_params: Fils join rsp params + * + * This API is used to send the received HLP packet in Assoc rsp(FILS AKM) + * to the network layer. + * + * Return: None + */ +void hdd_update_hlp_info(struct net_device *dev, tCsrRoamInfo *roam_info); +#else +static inline void hdd_update_hlp_info(struct net_device *dev, + tCsrRoamInfo *roam_info) +{} +#endif #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 59e9a33fb638..b5268e08148d 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2057,6 +2057,12 @@ static void hdd_send_re_assoc_event(struct net_device *dev, (u8 *)pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength, pCsrRoamInfo->nAssocReqLength); + wlan_hdd_save_gtk_offload_params(pAdapter, NULL, + pCsrRoamInfo->kek, + pCsrRoamInfo->kek_len, + pCsrRoamInfo->replay_ctr, + true, GTK_OFFLOAD_ENABLE); + hdd_debug("ReAssoc Req IE dump"); QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG, assoc_req_ies, pCsrRoamInfo->nAssocReqLength); @@ -2065,6 +2071,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev, assoc_req_ies, pCsrRoamInfo->nAssocReqLength, rspRsnIe, rspRsnLength, pCsrRoamInfo); + hdd_debug("Kek len %d", pCsrRoamInfo->kek_len); + + hdd_update_hlp_info(dev, pCsrRoamInfo); + done: sme_roam_free_connect_profile(&roam_profile); if (final_req_ie) @@ -2306,6 +2316,12 @@ void hdd_clear_fils_connection_info(hdd_adapter_t *adapter) qdf_mem_free(wext_state->roamProfile.fils_con_info); wext_state->roamProfile.fils_con_info = NULL; } + + if (wext_state->roamProfile.hlp_ie) { + qdf_mem_free(wext_state->roamProfile.hlp_ie); + wext_state->roamProfile.hlp_ie = NULL; + wext_state->roamProfile.hlp_ie_len = 0; + } } #endif diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 7f66db847499..8f56447d4a5d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4517,37 +4517,28 @@ wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, return ret; } -/** - * wlan_hdd_save_gtk_offload_params() - Save gtk offload parameters in STA - * context for offload operations. - * @adapter: Adapter context - * @kck_ptr: KCK buffer pointer - * @kek_ptr: KEK buffer pointer - * @replay_ctr: Pointer to 64 bit long replay counter - * @big_endian: true if replay_ctr is in big endian format - * @ul_flags: Offload flags - * - * Return: None - */ #ifdef WLAN_FEATURE_GTK_OFFLOAD -static void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, - uint8_t *kck_ptr, - uint8_t *kek_ptr, - uint8_t *replay_ctr, - bool big_endian, - uint32_t ul_flags) +void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, uint8_t *kck_ptr, + uint8_t *kek_ptr, uint32_t kek_len, + uint8_t *replay_ctr, bool big_endian, + uint32_t ul_flags) { hdd_station_ctx_t *hdd_sta_ctx; uint8_t *p; int i; hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - memcpy(hdd_sta_ctx->gtkOffloadReqParams.aKCK, kck_ptr, - NL80211_KCK_LEN); - memcpy(hdd_sta_ctx->gtkOffloadReqParams.aKEK, kek_ptr, - NL80211_KEK_LEN); + + if (kck_ptr) + qdf_mem_copy(hdd_sta_ctx->gtkOffloadReqParams.aKCK, kck_ptr, + NL80211_KCK_LEN); + + if (kek_ptr) + qdf_mem_copy(hdd_sta_ctx->gtkOffloadReqParams.aKEK, kek_ptr, + kek_len); qdf_copy_macaddr(&hdd_sta_ctx->gtkOffloadReqParams.bssid, &hdd_sta_ctx->conn_info.bssId); + hdd_sta_ctx->gtkOffloadReqParams.kek_len = kek_len; /* * changing from big to little endian since driver * works on little endian format @@ -4563,9 +4554,10 @@ static void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, hdd_sta_ctx->gtkOffloadReqParams.ulFlags = ul_flags; } #else -static void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, +void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, uint8_t *kck_ptr, uint8_t *kek_ptr, + uint32_t kek_len, uint8_t *replay_ctr, bool big_endian, uint32_t ul_flags) @@ -4573,6 +4565,51 @@ static void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, } #endif +#ifdef WLAN_FEATURE_FILS_SK +/** + * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth + * @skb: SK buffer + * @roam_info: Roam info + * + * API adds fils params[pmk, pmkid, next sequence number] to roam auth event + * + * Return: zero on success, error code on failure + */ +static int wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb, + tCsrRoamInfo *roam_info) +{ + + if (roam_info->pmk_len && + nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK, + roam_info->pmk_len, roam_info->pmk)) { + hdd_err("pmk send fail"); + return -EINVAL; + } + + if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID, + SIR_PMKID_LEN, roam_info->pmkid)) { + hdd_err("pmkid send fail"); + return -EINVAL; + } + + if (roam_info->update_erp_next_seq_num && + nla_put_u16(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM, + roam_info->next_erp_seq_num)) { + hdd_err("ERP seq num send fail"); + return -EINVAL; + } + + return 0; +} +#else +static inline int wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb, + tCsrRoamInfo + *roam_info) +{ + return 0; +} +#endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD /** * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event @@ -4608,6 +4645,8 @@ int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid, hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter); struct sk_buff *skb = NULL; eCsrAuthType auth_type; + uint32_t fils_params_len; + int status; ENTER(); @@ -4618,12 +4657,23 @@ int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid, !roam_info_ptr->roamSynchInProgress) return 0; + /* + * PMK is sent from FW in Roam Synch Event for FILS Roaming. + * In that case, add three more NL attributes.ie. PMK, PMKID + * and ERP next sequence number. Add corresponding lengths + * with 3 extra NL message headers for each of the + * aforementioned params. + */ + fils_params_len = roam_info_ptr->pmk_len + SIR_PMKID_LEN + + sizeof(uint16_t) + (3 * NLMSG_HDRLEN); + skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy, &(adapter->wdev), ETH_ALEN + req_rsn_len + rsp_rsn_len + sizeof(uint8_t) + SIR_REPLAY_CTR_LEN + - SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN + - sizeof(uint8_t) + (8 * NLMSG_HDRLEN), + SIR_KCK_KEY_LEN + roam_info_ptr->kek_len + + sizeof(uint8_t) + (8 * NLMSG_HDRLEN) + + fils_params_len, QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX, GFP_KERNEL); @@ -4668,11 +4718,16 @@ int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid, SIR_KCK_KEY_LEN, roam_info_ptr->kck) || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, - SIR_KEK_KEY_LEN, roam_info_ptr->kek)) { + roam_info_ptr->kek_len, roam_info_ptr->kek)) { hdd_err("nla put fail"); goto nla_put_failure; } + status = wlan_hdd_add_fils_params_roam_auth_event(skb, + roam_info_ptr); + if (status) + goto nla_put_failure; + /* * Save the gtk rekey parameters in HDD STA context. They will * be used next time when host enables GTK offload and goes @@ -4680,6 +4735,7 @@ int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid, */ wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck, roam_info_ptr->kek, + roam_info_ptr->kek_len, roam_info_ptr->replay_ctr, true, GTK_OFFLOAD_DISABLE); @@ -15272,6 +15328,56 @@ static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state, return 0; } +#ifdef WLAN_FEATURE_FILS_SK +/** + * wlan_hdd_save_hlp_ie - API to save HLP IE + * @roam_profile: Pointer to roam profile + * @gen_ie: IE buffer to store + * @len: length of the IE buffer @gen_ie + * @flush: Flush the older saved HLP if any + * + * Return: None + */ +static void wlan_hdd_save_hlp_ie(tCsrRoamProfile *roam_profile, + const uint8_t *gen_ie, uint16_t len, + bool flush) +{ + uint8_t *hlp_ie = roam_profile->hlp_ie; + + if (flush) { + roam_profile->hlp_ie_len = 0; + if (hlp_ie) { + qdf_mem_free(hlp_ie); + roam_profile->hlp_ie = NULL; + } + } + + if ((roam_profile->hlp_ie_len + + len) > FILS_MAX_HLP_DATA_LEN) { + hdd_err("HLP len exceeds: hlp_ie_len %d len %d", + roam_profile->hlp_ie_len, len); + return; + } + + if (!roam_profile->hlp_ie) { + roam_profile->hlp_ie = + qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN); + hlp_ie = roam_profile->hlp_ie; + if (!hlp_ie) { + hdd_err("HLP IE mem alloc fails"); + return; + } + } + + qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len); + roam_profile->hlp_ie_len += len; +} +#else +static inline void wlan_hdd_save_hlp_ie(tCsrRoamProfile *roam_profile, + const uint8_t *gen_ie, uint16_t len, + bool flush) +{} +#endif /** * wlan_hdd_cfg80211_set_ie() - set IEs * @pAdapter: Pointer to adapter @@ -15569,6 +15675,10 @@ static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie, if (genie[0] == SIR_FILS_HLP_EXT_EID) { hdd_debug("Set HLP EXT IE(len %d)", eLen + 2); + wlan_hdd_save_hlp_ie(&pWextState-> + roamProfile, + genie - 2, eLen + 2, + true); status = wlan_hdd_add_assoc_ie( pWextState, genie - 2, eLen + 2); @@ -15582,6 +15692,9 @@ static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie, case DOT11F_EID_FRAGMENT_IE: { hdd_debug("Set Fragment IE(len %d)", eLen + 2); + wlan_hdd_save_hlp_ie(&pWextState->roamProfile, + genie - 2, eLen + 2, + false); status = wlan_hdd_add_assoc_ie(pWextState, genie - 2, eLen + 2); if (status) @@ -17446,19 +17559,21 @@ static void hdd_fill_pmksa_info(tPmkidCacheInfo *pmk_cache, { if (pmksa->bssid) { hdd_debug("%s PMKSA for " MAC_ADDRESS_STR, - is_delete ? "Delete" : "Set", - MAC_ADDR_ARRAY(pmksa->bssid)); + is_delete ? "Delete" : "Set", + MAC_ADDR_ARRAY(pmksa->bssid)); qdf_mem_copy(pmk_cache->BSSID.bytes, - pmksa->bssid, QDF_MAC_ADDR_SIZE); + pmksa->bssid, QDF_MAC_ADDR_SIZE); } else { qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, - SIR_MAC_MAX_SSID_LENGTH); - qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id, CACHE_ID_LEN); + SIR_MAC_MAX_SSID_LENGTH); + qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id, + CACHE_ID_LEN); pmk_cache->ssid_len = pmksa->ssid_len; hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x", - is_delete ? "Delete" : "Set", - pmk_cache->ssid_len, pmk_cache->ssid_len, - pmksa->ssid, pmksa->cache_id[0], pmksa->cache_id[1]); + is_delete ? "Delete" : "Set", + pmk_cache->ssid_len, pmk_cache->ssid_len, + pmk_cache->ssid, pmk_cache->cache_id[0], + pmk_cache->cache_id[1]); } if (is_delete) @@ -17579,6 +17694,9 @@ static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, TRACE_CODE_HDD_CFG80211_SET_PMKSA, pAdapter->sessionId, result)); + sme_set_del_pmkid_cache(halHandle, pAdapter->sessionId, + &pmk_cache, true); + EXIT(); return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL; } @@ -17666,6 +17784,9 @@ static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, MAC_ADDR_ARRAY(pmksa->bssid)); status = -EINVAL; } + + sme_set_del_pmkid_cache(halHandle, pAdapter->sessionId, &pmk_cache, + false); EXIT(); return status; } @@ -17900,6 +18021,39 @@ void wlan_hdd_cfg80211_update_replay_counter_cb(void *callbackContext, tempReplayCounter, GFP_KERNEL); } +#ifdef CFG80211_REKEY_DATA_KEK_LEN +/** + * wlan_hdd_save_gtk_params() - Save GTK params + * @adapter: HDD adapter + * @data: Pointer to gtk rekey data + * + * Return: None + */ +static void wlan_hdd_save_gtk_params(hdd_adapter_t *adapter, + struct cfg80211_gtk_rekey_data *data) +{ + wlan_hdd_save_gtk_offload_params(adapter, + (uint8_t *)data->kck, + (uint8_t *)data->kek, + (uint32_t)data->kek_len, + (uint8_t *)data->replay_ctr, + true, + GTK_OFFLOAD_ENABLE); +} +#else +static void wlan_hdd_save_gtk_params(hdd_adapter_t *adapter, + struct cfg80211_gtk_rekey_data *data) +{ + wlan_hdd_save_gtk_offload_params(adapter, + (uint8_t *)data->kck, + (uint8_t *)data->kek, + NL80211_KEK_LEN, + (uint8_t *)data->replay_ctr, + true, + GTK_OFFLOAD_ENABLE); +} +#endif + /** * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data * @wiphy: Pointer to wiphy @@ -17955,12 +18109,8 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, * Save gtk rekey parameters in HDD STA context. They will be used * repeatedly when host goes into power save mode. */ - wlan_hdd_save_gtk_offload_params(adapter, - (uint8_t *)data->kck, - (uint8_t *)data->kek, - (uint8_t *)data->replay_ctr, - true, - GTK_OFFLOAD_ENABLE); + wlan_hdd_save_gtk_params(adapter, data); + hdd_debug("replay counter from supplicant 0x%llx, value stored in ullKeyReplayCounter 0x%llx", *((uint64_t *)data->replay_ctr), hdd_sta_ctx->gtkOffloadReqParams.ullKeyReplayCounter); @@ -18759,6 +18909,169 @@ void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter) return; } +#if defined(WLAN_FEATURE_FILS_SK) &&\ + (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\ + (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))) + +#ifndef UPDATE_FILS_ERP_INFO +#define UPDATE_FILS_ERP_INFO BIT(1) +#endif + +#ifndef UPDATE_FILS_AUTH_TYPE +#define UPDATE_FILS_AUTH_TYPE BIT(2) +#endif + +/** + * __wlan_hdd_cfg80211_update_connect_params - update connect params + * @wiphy: Handle to struct wiphy to get handle to module context. + * @dev: Pointer to network device + * @req: Pointer to connect params + * @changed: Bitmap used to indicate the changed params + * + * Update the connect parameters while connected to a BSS. The updated + * parameters can be used by driver/firmware for subsequent BSS selection + * (roaming) decisions and to form the Authentication/(Re)Association + * Request frames. This call does not request an immediate disassociation + * or reassociation with the current BSS, i.e., this impacts only + * subsequent (re)associations. The bits in changed are defined in enum + * cfg80211_connect_params_changed + * + * Return: zero for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_update_connect_params( + struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *req, uint32_t changed) +{ + hdd_wext_state_t *wext_state; + tCsrRoamProfile *roam_profile; + uint8_t *buf; + int ret, auth_type; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + QDF_STATUS status; + struct cds_fils_connection_info *fils_info; + + ENTER_DEV(dev); + + if (wlan_hdd_validate_session_id(adapter->sessionId)) { + hdd_err("invalid session id: %d", adapter->sessionId); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return -EINVAL; + + wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); + roam_profile = &wext_state->roamProfile; + fils_info = roam_profile->fils_con_info; + + if (!fils_info) { + hdd_err("No valid FILS conn info"); + return -EINVAL; + } + + if (req->ie_len) + wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len); + + if (changed) + fils_info->is_fils_connection = true; + + if (changed & UPDATE_FILS_ERP_INFO) { + if ((req->fils_erp_username_len > + FILS_MAX_KEYNAME_NAI_LENGTH) || + (req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH) || + (req->fils_erp_realm_len > FILS_MAX_REALM_LEN)) { + hdd_err("Invalid length: username len %zd, rrk len %zd realm len %zd", + req->fils_erp_username_len, + req->fils_erp_rrk_len, + req->fils_erp_realm_len); + return -EINVAL; + } + + fils_info->key_nai_length = req->fils_erp_username_len + + sizeof(char) + + req->fils_erp_realm_len; + if (req->fils_erp_username_len && req->fils_erp_username) { + buf = fils_info->keyname_nai; + qdf_mem_copy(buf, req->fils_erp_username, + req->fils_erp_username_len); + buf += req->fils_erp_username_len; + *buf++ = '@'; + qdf_mem_copy(buf, req->fils_erp_realm, + req->fils_erp_realm_len); + } + + fils_info->sequence_number = req->fils_erp_next_seq_num; + fils_info->r_rk_length = req->fils_erp_rrk_len; + + if (req->fils_erp_rrk_len && req->fils_erp_rrk) + qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk, + fils_info->r_rk_length); + + fils_info->realm_len = req->fils_erp_realm_len; + if (req->fils_erp_realm_len && req->fils_erp_realm) + qdf_mem_copy(fils_info->realm, req->fils_erp_realm, + fils_info->realm_len); + } + + if (changed & UPDATE_FILS_AUTH_TYPE) { + auth_type = wlan_hdd_get_fils_auth_type(req->auth_type); + if (auth_type < 0) { + hdd_err("invalid auth type for fils %d", + req->auth_type); + return -EINVAL; + } + + roam_profile->fils_con_info->auth_type = auth_type; + } + + hdd_debug("fils conn update: changed %x is_fils %d seq=%d auth=%d user_len=%zu rrk_len=%zu realm_len=%zu keyname nai len %d", + changed, roam_profile->fils_con_info-> + is_fils_connection, req->fils_erp_next_seq_num, + req->auth_type, req->fils_erp_username_len, + req->fils_erp_rrk_len, req->fils_erp_realm_len, + roam_profile->fils_con_info->key_nai_length); + + if (!adapter->fast_roaming_allowed) { + hdd_debug("LFR3 not enabled on this interface"); + return 0; + } + + status = sme_update_fils_config(hdd_ctx->hHal, adapter->sessionId, + roam_profile); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Update FILS connect params to Fw failed %d", status); + + return 0; +} + +/** + * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for + * __wlan_hdd_cfg80211_update_connect_params + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device + * @req: Pointer to connect params + * @changed: flags used to indicate the changed params + * + * Return: zero for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_connect_params *req, + uint32_t changed) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev, + req, changed); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + /** * wlan_hdd_chan_info_cb() - channel info callback * @chan_info: struct scan_chan_info @@ -18943,6 +19256,7 @@ void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx) * @set_ap_chanwidth = Set AP channel bandwidth * @dump_survey = Dump survey * @key_mgmt_set_pmk = Set pmk key management + * @update_connect_params = Update connect params */ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { .add_virtual_intf = wlan_hdd_add_virtual_intf, @@ -19011,4 +19325,9 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { defined(CFG80211_ABORT_SCAN) .abort_scan = wlan_hdd_cfg80211_abort_scan, #endif +#if defined(WLAN_FEATURE_FILS_SK) &&\ + (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\ + (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))) + .update_connect_params = wlan_hdd_cfg80211_update_connect_params, +#endif }; diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 88e588b6de00..4b6849174153 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -608,4 +608,25 @@ void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx); * Return: none */ void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx); + +/** + * wlan_hdd_save_gtk_offload_params() - Save gtk offload parameters in STA + * context for offload operations. + * @adapter: Adapter context + * @kck_ptr: KCK buffer pointer + * @kek_ptr: KEK buffer pointer + * @kek_len: KEK length + * @replay_ctr: Pointer to 64 bit long replay counter + * @big_endian: true if replay_ctr is in big endian format + * @ul_flags: Offload flags + * + * Return: None + */ +void wlan_hdd_save_gtk_offload_params(hdd_adapter_t *adapter, + uint8_t *kck_ptr, + uint8_t *kek_ptr, + uint32_t kek_len, + uint8_t *replay_ctr, + bool big_endian, + uint32_t ul_flags); #endif diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6f4d1645a1e3..83af758f7729 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4524,27 +4524,27 @@ static inline void hdd_populate_fils_params(struct cfg80211_connect_resp_params { } #endif -/** - * hdd_update_hlp_info() - Update HLP packet received in FILS assoc rsp - * @dev: net device - * @roam_fils_params: Fils join rsp params - * - * This API is used to send the received HLP packet in Assoc rsp(FILS AKM) - * to the network layer. - * - * Return: None - */ -static void hdd_update_hlp_info(struct net_device *dev, - struct fils_join_rsp_params *roam_fils_params) +void hdd_update_hlp_info(struct net_device *dev, tCsrRoamInfo *roam_info) { struct sk_buff *skb; uint16_t skb_len; struct llc_snap_hdr_t *llc_hdr; QDF_STATUS status; - uint8_t *hlp_data = roam_fils_params->hlp_data; - uint16_t hlp_data_len = roam_fils_params->hlp_data_len; + uint8_t *hlp_data; + uint16_t hlp_data_len; + struct fils_join_rsp_params *roam_fils_params + = roam_info->fils_join_rsp; hdd_adapter_t *padapter = WLAN_HDD_GET_PRIV_PTR(dev); + if (!roam_fils_params) + return; + + if (!roam_fils_params->hlp_data_len || !roam_fils_params->hlp_data) + return; + + hlp_data = roam_fils_params->hlp_data; + hlp_data_len = roam_fils_params->hlp_data_len; + /* Calculate skb length */ skb_len = (2 * ETH_ALEN) + hlp_data_len; skb = qdf_nbuf_alloc(NULL, skb_len, 0, 4, false); @@ -4596,7 +4596,6 @@ static void hdd_update_hlp_info(struct net_device *dev, * @gfp: allocation flags * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp * @timeout_reason: reason for connect timeout - * @roam_fils_params: FILS join response params * * This API is used as wrapper to send FILS key/sequence number * params etc. to supplicant in case of FILS connection @@ -4608,10 +4607,13 @@ static void hdd_connect_done(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, u16 status, gfp_t gfp, bool connect_timeout, tSirResultCodes - timeout_reason, struct fils_join_rsp_params - *roam_fils_params) + timeout_reason) { struct cfg80211_connect_resp_params fils_params; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct fils_join_rsp_params *roam_fils_params = + roam_info->fils_join_rsp; + qdf_mem_zero(&fils_params, sizeof(fils_params)); if (!roam_fils_params) { @@ -4633,6 +4635,11 @@ static void hdd_connect_done(struct net_device *dev, const u8 *bssid, roam_fils_params->fils_pmk_len, roam_fils_params->fils_pmkid, roam_info->fils_seq_num); + wlan_hdd_save_gtk_offload_params(adapter, NULL, + roam_fils_params->kek, + roam_fils_params->kek_len, + roam_info->replay_ctr, + true, GTK_OFFLOAD_ENABLE); } hdd_debug("FILS indicate connect status %d seq no %d", fils_params.status, @@ -4641,7 +4648,7 @@ static void hdd_connect_done(struct net_device *dev, const u8 *bssid, cfg80211_connect_done(dev, &fils_params, gfp); if (roam_fils_params && roam_fils_params->hlp_data_len) - hdd_update_hlp_info(dev, roam_fils_params); + hdd_update_hlp_info(dev, roam_info); /* Clear all the FILS key info */ if (roam_fils_params && roam_fils_params->fils_pmk) @@ -4657,13 +4664,7 @@ static inline void hdd_connect_done(struct net_device *dev, const u8 *bssid, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, u16 status, gfp_t gfp, bool connect_timeout, tSirResultCodes - timeout_reason, struct fils_join_rsp_params - *roam_fils_params) -{ } - -static inline void hdd_update_hlp_info(struct net_device *dev, - struct fils_join_rsp_params *roam_fils_params) - + timeout_reason) { } #endif #endif @@ -4704,7 +4705,7 @@ static int hdd_fils_update_connect_results(struct net_device *dev, hdd_connect_done(dev, bssid, bss, roam_info, req_ie, req_ie_len, resp_ie, resp_ie_len, status, gfp, connect_timeout, - timeout_reason, roam_info->fils_join_rsp); + timeout_reason); return 0; } #else diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index d5c98f150c29..26cf04bcab14 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -810,7 +810,8 @@ static int hdd_set_grat_arp_keepalive(hdd_adapter_t *adapter) * This function performs the work initially trigged by a callback * from the IPv4 netdev notifier. Since this means there has been a * change in IPv4 state for the interface, the ARP offload is - * reconfigured. + * reconfigured. Also, Updates the HLP IE info with IP address info + * to fw if LFR3 is enabled * * Return: None */ @@ -823,6 +824,9 @@ static void __hdd_ipv4_notifier_work_queue(struct work_struct *work) int status; bool ndi_connected; bool sta_associated; + hdd_wext_state_t *wext_state; + tCsrRoamProfile *roam_profile; + struct in_ifaddr *ifa; hdd_debug("Configuring ARP Offload"); @@ -855,6 +859,13 @@ static void __hdd_ipv4_notifier_work_queue(struct work_struct *work) if (pHddCtx->config->sta_keepalive_method == HDD_STA_KEEPALIVE_GRAT_ARP) hdd_set_grat_arp_keepalive(pAdapter); + + wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + roam_profile = &wext_state->roamProfile; + ifa = hdd_lookup_ifaddr(pAdapter); + if (ifa) + sme_send_hlp_ie_info(pHddCtx->hHal, pAdapter->sessionId, + roam_profile, ifa->ifa_local); } /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 79cc0a2484ee..961bbb4e9207 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -14002,6 +14002,8 @@ static int hdd_set_wext(hdd_adapter_t *pAdapter) static void hdd_initialize_fils_info(hdd_wext_state_t *pwextBuf) { pwextBuf->roamProfile.fils_con_info = NULL; + pwextBuf->roamProfile.hlp_ie = NULL; + pwextBuf->roamProfile.hlp_ie_len = 0; } #else static void hdd_initialize_fils_info(hdd_wext_state_t *pwextBuf) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4fe7c72ad9c8..757ed7467147 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -200,7 +200,10 @@ typedef enum { #define SIR_BTK_KEY_LEN 32 #define SIR_KCK_KEY_LEN 16 #define SIR_KEK_KEY_LEN 16 +#define SIR_KEK_KEY_LEN_FILS 64 #define SIR_REPLAY_CTR_LEN 8 +#define SIR_PMK_LEN 48 +#define SIR_PMKID_LEN 16 #ifdef WLAN_FEATURE_ROAM_OFFLOAD #define SIR_UAPSD_BITOFFSET_ACVO 0 #define SIR_UAPSD_BITOFFSET_ACVI 1 @@ -3457,6 +3460,10 @@ typedef struct sSirRoamOffloadScanReq { enum wmi_dwelltime_adaptive_mode roamscan_adaptive_dwell_mode; tSirAddie assoc_ie; struct lca_disallow_config_params lca_config_params; +#ifdef WLAN_FEATURE_FILS_SK + bool is_fils_connection; + struct roam_fils_params roam_fils_params; +#endif } tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; typedef struct sSirRoamOffloadScanRsp { @@ -3584,9 +3591,10 @@ typedef struct { * WMA_GTK_OFFLOAD_REQ *--------------------------------------------------------------------------*/ typedef struct { - uint32_t ulFlags; /* optional flags */ - uint8_t aKCK[16]; /* Key confirmation key */ - uint8_t aKEK[16]; /* key encryption key */ + uint32_t ulFlags; /* optional flags */ + uint8_t aKCK[SIR_KCK_KEY_LEN]; /* Key confirmation key */ + uint8_t aKEK[SIR_KEK_KEY_LEN_FILS]; /* key encryption key */ + uint32_t kek_len; uint64_t ullKeyReplayCounter; /* replay counter */ struct qdf_mac_addr bssid; } tSirGtkOffloadParams, *tpSirGtkOffloadParams; @@ -4720,13 +4728,23 @@ typedef struct sSirSmeRoamOffloadSynchInd { uint8_t roamReason; uint32_t chan_freq; uint8_t kck[SIR_KCK_KEY_LEN]; - uint8_t kek[SIR_KEK_KEY_LEN]; + uint32_t kek_len; + uint8_t kek[SIR_KEK_KEY_LEN_FILS]; + uint32_t pmk_len; + uint8_t pmk[SIR_PMK_LEN]; + uint8_t pmkid[SIR_PMKID_LEN]; + bool update_erp_next_seq_num; + uint16_t next_erp_seq_num; uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; void *add_bss_params; tpSirSmeJoinRsp join_rsp; uint16_t aid; struct sir_hw_mode_trans_ind hw_mode_trans_ind; uint8_t nss; + struct qdf_mac_addr dst_mac; + struct qdf_mac_addr src_mac; + uint16_t hlp_data_len; + uint8_t hlp_data[FILS_MAX_HLP_DATA_LEN]; } roam_offload_synch_ind; #ifdef WLAN_FEATURE_ROAM_OFFLOAD diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index b8db6513fd55..f15d773cc67e 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -677,6 +677,8 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_SET_LIMIT_OFF_CHAN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 388) +#define SIR_HAL_SET_DEL_PMKID_CACHE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 389) +#define SIR_HAL_HLP_IE_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 390) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ #define SIR_CFG_MSG_TYPES_BEGIN (SIR_CFG_MODULE_ID << 8) diff --git a/core/mac/src/pe/include/lim_fils_defs.h b/core/mac/src/pe/include/lim_fils_defs.h index cb845b26386b..48919e84a434 100644 --- a/core/mac/src/pe/include/lim_fils_defs.h +++ b/core/mac/src/pe/include/lim_fils_defs.h @@ -111,6 +111,8 @@ #define KDE_OUI_TYPE "\x00\x0F\xAC" #define KDE_OUI_TYPE_SIZE 3 +#define SINGLE_ELEMENT_HASH_CNT 1 + /* * struct eap_auth_reserved: this structure defines flags format in eap packets * as defined in RFC 6696 5.3.1 @@ -186,10 +188,10 @@ struct fils_auth_rsp_info { * @cipher: cipher type * @fils_erp_reauth_pkt: pointer to fils reauth packet data * @fils_erp_reauth_pkt_len: reauth packet length - * @fils_r_rk: pointer to fils rRk - * @fils_r_rk_len: fils rRk length - * @fils_r_ik: pointer to fils rIk - * @fils_r_ik_len: fils rIk length + * @fils_rrk: pointer to fils rRk + * @fils_rrk_len: fils rRk length + * @fils_rik: pointer to fils rIk + * @fils_rik_len: fils rIk length * @sequence_number: sequence number needs to be used in eap packet * @fils_session: fils session IE element * @fils_nonce: fils snonce @@ -233,10 +235,10 @@ struct pe_fils_session { uint8_t cipher; uint8_t *fils_erp_reauth_pkt; uint32_t fils_erp_reauth_pkt_len; - uint8_t *fils_r_rk; - uint8_t fils_r_rk_len; - uint8_t *fils_r_ik; - uint32_t fils_r_ik_len; + uint8_t *fils_rrk; + uint8_t fils_rrk_len; + uint8_t *fils_rik; + uint32_t fils_rik_len; uint16_t sequence_number; uint8_t fils_session[SIR_FILS_SESSION_LENGTH]; uint8_t fils_nonce[SIR_FILS_NONCE_LENGTH]; diff --git a/core/mac/src/pe/include/lim_process_fils.h b/core/mac/src/pe/include/lim_process_fils.h index 68829eb3973d..422291e7af76 100644 --- a/core/mac/src/pe/include/lim_process_fils.h +++ b/core/mac/src/pe/include/lim_process_fils.h @@ -62,6 +62,25 @@ bool lim_is_valid_fils_auth_frame(tpAniSirGlobal mac_ctx, tpPESession pe_session, tSirMacAuthFrameBody *rx_auth_frm_body); /** + * lim_create_fils_rik()- This API create rik using rrk coming from + * supplicant. + * @rrk: input rrk + * @rrk_len: rrk length + * @rik: Created rik + * @rik_len: rik length to be filled + * + * rIK = KDF (K, S), where + * K = rRK and + * S = rIK Label + "\0" + cryptosuite + length + * The rIK Label is the 8-bit ASCII string: + * Re-authentication Integrity Key@ietf.org + * + * Return: QDF_STATUS + */ +QDF_STATUS lim_create_fils_rik(uint8_t *rrk, uint8_t rrk_len, + uint8_t *rik, uint32_t *rik_len); + +/** * lim_update_fils_config()- This API updates fils session info to csr config * from join request. * @session: PE session @@ -178,6 +197,19 @@ bool lim_verify_fils_params_assoc_rsp(tpAniSirGlobal mac_ctx, tpPESession session_entry, tpSirAssocRsp assoc_rsp, tLimMlmAssocCnf *assoc_cnf); + +/** + * lim_update_fils_rik() - API to update FILS RIK in RSO + * @pe_session: PE Session + * @req_buffer: Pointer to RSO request + * + * This API is used to calculate(if required) RIK and fill + * the same in RSO request to fw. + * + * Return: None + */ +void lim_update_fils_rik(tpPESession pe_session, + tSirRoamOffloadScanReq *req_buffer); #else static inline bool lim_process_fils_auth_frame2(tpAniSirGlobal mac_ctx, tpPESession pe_session, tSirMacAuthFrameBody *rx_auth_frm_body) @@ -244,4 +276,8 @@ static inline bool lim_verify_fils_params_assoc_rsp(tpAniSirGlobal mac_ctx, { return true; } + +static inline void lim_update_fils_rik(tpPESession pe_session, + tSirRoamOffloadScanReq *req_buffer) +{ } #endif diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 009710ba7572..fc07e1dfadf9 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -495,6 +495,10 @@ typedef struct sPESession /* Added to Support BT-AMP */ uint8_t lim_non_ecsa_cap_num; #ifdef WLAN_FEATURE_FILS_SK struct pe_fils_session *fils_info; + struct qdf_mac_addr dst_mac; + struct qdf_mac_addr src_mac; + uint16_t hlp_data_len; + uint8_t *hlp_data; #endif uint8_t deauthmsgcnt; uint8_t disassocmsgcnt; diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 2018ed740544..7f3497f008ea 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1972,6 +1972,45 @@ lim_roam_fill_bss_descr(tpAniSirGlobal pMac, qdf_mem_free(parsed_frm_ptr); return QDF_STATUS_SUCCESS; } + +#if defined(WLAN_FEATURE_FILS_SK) +/** + * lim_copy_and_free_hlp_data_from_session - Copy HLP info + * @session_ptr: PE session + * @roam_sync_ind_ptr: Roam Synch Indication pointer + * + * This API is used to copy the parsed HLP info from PE session + * to roam synch indication data. THe HLP info is expected to be + * parsed/stored in PE session already from assoc IE's received + * from fw as part of Roam Synch Indication. + * + * Return: None + */ +static void lim_copy_and_free_hlp_data_from_session(tpPESession session_ptr, + roam_offload_synch_ind *roam_sync_ind_ptr) +{ + if (session_ptr->hlp_data && session_ptr->hlp_data_len) { + cds_copy_hlp_info(&session_ptr->dst_mac, + &session_ptr->src_mac, + session_ptr->hlp_data_len, + session_ptr->hlp_data, + &roam_sync_ind_ptr->dst_mac, + &roam_sync_ind_ptr->src_mac, + &roam_sync_ind_ptr->hlp_data_len, + roam_sync_ind_ptr->hlp_data); + qdf_mem_free(session_ptr->hlp_data); + session_ptr->hlp_data = NULL; + session_ptr->hlp_data_len = 0; + } +} +#else +static inline void lim_copy_and_free_hlp_data_from_session( + tpPESession session_ptr, + roam_offload_synch_ind + *roam_sync_ind_ptr) +{} +#endif + /** * pe_roam_synch_callback() - PE level callback for roam synch propagation * @mac_ctx: MAC Context @@ -2118,8 +2157,13 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, mac_ctx->roam.pReassocResp, mac_ctx->roam.reassocRespLen); ft_session_ptr->bRoamSynchInProgress = true; + lim_process_assoc_rsp_frame(mac_ctx, mac_ctx->roam.pReassocResp, LIM_REASSOC, ft_session_ptr); + + lim_copy_and_free_hlp_data_from_session(ft_session_ptr, + roam_sync_ind_ptr); + roam_sync_ind_ptr->aid = ft_session_ptr->limAID; curr_sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; diff --git a/core/mac/src/pe/lim/lim_process_fils.c b/core/mac/src/pe/lim/lim_process_fils.c index 981d9f715947..e655a7d66361 100644 --- a/core/mac/src/pe/lim/lim_process_fils.c +++ b/core/mac/src/pe/lim/lim_process_fils.c @@ -667,8 +667,8 @@ static void lim_generate_rmsk_data(tpPESession pe_session) return; auth_info = &(pe_session->fils_info->auth_info); - fils_info->fils_rmsk_len = fils_info->fils_r_rk_len; - fils_info->fils_rmsk = qdf_mem_malloc(fils_info->fils_r_rk_len); + fils_info->fils_rmsk_len = fils_info->fils_rrk_len; + fils_info->fils_rmsk = qdf_mem_malloc(fils_info->fils_rrk_len); if (!fils_info->fils_rmsk) { pe_err("failed to alloc memory"); return; @@ -679,9 +679,9 @@ static void lim_generate_rmsk_data(tpPESession pe_session) * it should be in network byte order */ lim_copy_u16_be(&optional_data[0], fils_info->sequence_number); - lim_copy_u16_be(&optional_data[2], fils_info->fils_r_rk_len); - lim_default_hmac_sha256_kdf(fils_info->fils_r_rk, - fils_info->fils_r_rk_len, rmsk_label, + lim_copy_u16_be(&optional_data[2], fils_info->fils_rrk_len); + lim_default_hmac_sha256_kdf(fils_info->fils_rrk, + fils_info->fils_rrk_len, rmsk_label, optional_data, sizeof(optional_data), fils_info->fils_rmsk, fils_info->fils_rmsk_len); lim_fils_data_dump("RMSK", fils_info->fils_rmsk, @@ -770,8 +770,10 @@ static QDF_STATUS lim_process_auth_wrapped_data(tpPESession pe_session, input_len[0] -= auth_tag_len; /* if we have auth tag remaining */ if (remaining_len == auth_tag_len) { - qdf_get_hmac_hash(FILS_SHA256_CRYPTO_TYPE, fils_info->fils_r_ik, - fils_info->fils_r_ik_len, 1, + qdf_get_hmac_hash(FILS_SHA256_CRYPTO_TYPE, + fils_info->fils_rik, + fils_info->fils_rik_len, + SINGLE_ELEMENT_HASH_CNT, input_data, input_len, hash); } else { pe_err("invalid remaining len %d", @@ -826,51 +828,32 @@ bool lim_is_valid_fils_auth_frame(tpAniSirGlobal mac_ctx, return true; } -/** - * lim_create_fils_r_ik()- This API create rik using rrk coming from - * supplicant. - * rIK = KDF (K, S), where - * K = rRK and - * S = rIK Label + "\0" + cryptosuite + length - * The rIK Label is the 8-bit ASCII string: - * Re-authentication Integrity Key@ietf.org - * @fils_info: fils session info - * - * Return: None - */ -static QDF_STATUS lim_create_fils_r_ik(struct pe_fils_session *fils_info) +QDF_STATUS lim_create_fils_rik(uint8_t *rrk, uint8_t rrk_len, + uint8_t *rik, uint32_t *rik_len) { uint8_t optional_data[SIR_FILS_OPTIONAL_DATA_LEN]; uint8_t label[] = SIR_FILS_RIK_LABEL; - if (!fils_info) + if (!rrk || !rik) return QDF_STATUS_E_FAILURE; optional_data[0] = HMAC_SHA256_128; /* basic validation */ - if (fils_info->fils_r_rk_len <= 0) { - pe_err("invalid r_rk length %d", fils_info->fils_r_rk_len); + if (rrk_len <= 0) { + pe_err("invalid r_rk length %d", rrk_len); return QDF_STATUS_E_FAILURE; } - lim_copy_u16_be(&optional_data[1], fils_info->fils_r_rk_len); - fils_info->fils_r_ik = qdf_mem_malloc(fils_info->fils_r_rk_len); - if (!fils_info->fils_r_ik) { - pe_err("failed to alloc memory"); - return QDF_STATUS_E_FAILURE; - } - if (lim_default_hmac_sha256_kdf(fils_info->fils_r_rk, - fils_info->fils_r_rk_len, label, + lim_copy_u16_be(&optional_data[1], rrk_len); + if (lim_default_hmac_sha256_kdf(rrk, rrk_len, label, optional_data, sizeof(optional_data), - fils_info->fils_r_ik, fils_info->fils_r_rk_len) + rik, rrk_len) != QDF_STATUS_SUCCESS) { - pe_err("failed to create r_ik"); + pe_err("failed to create rik"); return QDF_STATUS_E_FAILURE; } - fils_info->fils_r_ik_len = fils_info->fils_r_rk_len; - lim_fils_data_dump("rRk", fils_info->fils_r_rk, - fils_info->fils_r_rk_len); - lim_fils_data_dump("rIk", fils_info->fils_r_ik, - fils_info->fils_r_rk_len); + *rik_len = rrk_len; + lim_fils_data_dump("rRk", rrk, rrk_len); + lim_fils_data_dump("rIk", rik, *rik_len); return QDF_STATUS_SUCCESS; } @@ -880,13 +863,14 @@ static QDF_STATUS lim_create_fils_r_ik(struct pe_fils_session *fils_info) * sent in auth request. * @fils_info: fils session info * - * Return: None + * Return: length of the created wrapped data */ static int lim_create_fils_wrapper_data(struct pe_fils_session *fils_info) { uint8_t *buf; uint8_t auth_tag[FILS_AUTH_TAG_MAX_LENGTH] = {0}; uint32_t length = 0; + QDF_STATUS status; int buf_len = /* code + identifier */ sizeof(uint8_t) * 2 + @@ -955,12 +939,31 @@ static int lim_create_fils_wrapper_data(struct pe_fils_session *fils_info) * This should be moved to just after sending probe to save time * lim_process_switch_channel_join_req ?? */ - lim_create_fils_r_ik(fils_info); + fils_info->fils_rik = qdf_mem_malloc(fils_info->fils_rrk_len); + if (!fils_info->fils_rik) { + qdf_mem_free(fils_info->fils_erp_reauth_pkt); + fils_info->fils_erp_reauth_pkt = NULL; + pe_err("failed to alloc memory"); + return -EINVAL; + } + status = lim_create_fils_rik(fils_info->fils_rrk, + fils_info->fils_rrk_len, + fils_info->fils_rik, + &fils_info->fils_rik_len); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("RIK create fails"); + qdf_mem_free(fils_info->fils_erp_reauth_pkt); + qdf_mem_free(fils_info->fils_rik); + fils_info->fils_erp_reauth_pkt = NULL; + fils_info->fils_rik = NULL; + return -EINVAL; + } + fils_info->fils_erp_reauth_pkt_len = buf_len; length = fils_info->fils_erp_reauth_pkt_len - lim_get_auth_tag_len(HMAC_SHA256_128); qdf_get_hmac_hash(FILS_SHA256_CRYPTO_TYPE, - fils_info->fils_r_ik, fils_info->fils_r_ik_len, 1, + fils_info->fils_rik, fils_info->fils_rik_len, 1, &fils_info->fils_erp_reauth_pkt, &length, auth_tag); lim_fils_data_dump("Auth tag", auth_tag, @@ -1136,7 +1139,7 @@ void lim_update_fils_config(tpPESession session, fils_config_info->is_fils_connection; csr_fils_info->keyname_nai_length = fils_config_info->key_nai_length; - csr_fils_info->fils_r_rk_len = + csr_fils_info->fils_rrk_len = fils_config_info->r_rk_length; csr_fils_info->akm = fils_config_info->akm_type; csr_fils_info->auth = fils_config_info->auth_type; @@ -1150,16 +1153,16 @@ void lim_update_fils_config(tpPESession session, qdf_mem_copy(csr_fils_info->keyname_nai_data, fils_config_info->keyname_nai, fils_config_info->key_nai_length); - csr_fils_info->fils_r_rk = + csr_fils_info->fils_rrk = qdf_mem_malloc(fils_config_info->r_rk_length); - if (!csr_fils_info->fils_r_rk) { + if (!csr_fils_info->fils_rrk) { pe_err("failed to alloc memory"); qdf_mem_free(csr_fils_info->keyname_nai_data); return; } if (fils_config_info->r_rk_length <= FILS_MAX_RRK_LENGTH) - qdf_mem_copy(csr_fils_info->fils_r_rk, + qdf_mem_copy(csr_fils_info->fils_rrk, fils_config_info->r_rk, fils_config_info->r_rk_length); @@ -1176,7 +1179,7 @@ void lim_update_fils_config(tpPESession session, qdf_mem_malloc(fils_config_info->pmk_len); if (!csr_fils_info->fils_pmk) { qdf_mem_free(csr_fils_info->keyname_nai_data); - qdf_mem_free(csr_fils_info->fils_r_rk); + qdf_mem_free(csr_fils_info->fils_rrk); pe_err("failed to alloc memory"); return; } @@ -1213,9 +1216,9 @@ uint32_t lim_create_fils_auth_data(tpAniSirGlobal mac_ctx, return 0; /* These memory may already been allocated if auth retry */ - if (session->fils_info->fils_r_ik) { - qdf_mem_free(session->fils_info->fils_r_ik); - session->fils_info->fils_r_ik = NULL; + if (session->fils_info->fils_rik) { + qdf_mem_free(session->fils_info->fils_rik); + session->fils_info->fils_rik = NULL; } if (session->fils_info->fils_erp_reauth_pkt) { qdf_mem_free(session->fils_info->fils_erp_reauth_pkt); @@ -1302,7 +1305,6 @@ void populate_fils_connect_params(tpAniSirGlobal mac_ctx, fils_join_rsp->hlp_data); pe_debug("FILS connect params copied lim"); - pe_delete_fils_info(session); } /** @@ -1407,12 +1409,14 @@ bool lim_verify_fils_params_assoc_rsp(tpAniSirGlobal mac_ctx, tDot11fIEfils_kde fils_kde = assoc_rsp->fils_kde; QDF_STATUS status; - if (!fils_info) - return true; - if (!lim_is_fils_connection(session_entry)) return true; + if (!fils_info) { + pe_err("FILS Info not present"); + goto verify_fils_params_fails; + } + if (!assoc_rsp->fils_session.present) { pe_err("FILS IE not present"); goto verify_fils_params_fails; @@ -1820,4 +1824,51 @@ QDF_STATUS aead_decrypt_assoc_rsp(tpAniSirGlobal mac_ctx, (*n_frame) -= AES_BLOCK_SIZE; return status; } + +void lim_update_fils_rik(tpPESession pe_session, + tSirRoamOffloadScanReq *req_buffer) +{ + struct pe_fils_session *pe_fils_info = pe_session->fils_info; + struct roam_fils_params *roam_fils_params = + &req_buffer->roam_fils_params; + + if (!roam_fils_params) + return; + + /* + * If it is first connection, LIM session entries will not be + * set with FILS. However in RSO, CSR filled the RRK, realm + * info and is_fils_connection to true in req_buffer, RIK + * can be created with RRK and send all the FILS info to fw + */ + if ((!lim_is_fils_connection(pe_session) || + !pe_fils_info) && (req_buffer->is_fils_connection)) { + if (roam_fils_params->rrk_length > FILS_MAX_RRK_LENGTH) { + pe_err("FILS rrk len(%d) max (%d)", + roam_fils_params->rrk_length, + FILS_MAX_RRK_LENGTH); + return; + } + + lim_create_fils_rik(roam_fils_params->rrk, + roam_fils_params->rrk_length, + roam_fils_params->rik, + &roam_fils_params->rik_length); + pe_debug("Fils created rik len %d", + roam_fils_params->rik_length); + return; + } + + if ((pe_fils_info->fils_rik_len > FILS_MAX_RIK_LENGTH) || + !pe_fils_info->fils_rik) { + pe_err("Fils rik len(%d) max %d", pe_fils_info->fils_rik_len, + FILS_MAX_RIK_LENGTH); + return; + } + + roam_fils_params->rik_length = pe_fils_info->fils_rik_len; + qdf_mem_copy(roam_fils_params->rik, pe_fils_info->fils_rik, + roam_fils_params->rik_length); + pe_debug("fils rik len %d", roam_fils_params->rik_length); +} #endif diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index a54621ea54be..42e5aa69a0a3 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4061,6 +4061,9 @@ static void __lim_process_roam_scan_offload_req(tpAniSirGlobal mac_ctx, } qdf_mem_free(local_ie_buf); + if (pe_session) + lim_update_fils_rik(pe_session, req_buffer); + wma_msg.type = WMA_ROAM_SCAN_OFFLOAD_REQ; wma_msg.bodyptr = req_buffer; diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index a1c7acc571b4..2fd33ac2e98b 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -293,10 +293,10 @@ void pe_delete_fils_info(tpPESession session) qdf_mem_free(fils_info->keyname_nai_data); if (fils_info->fils_erp_reauth_pkt) qdf_mem_free(fils_info->fils_erp_reauth_pkt); - if (fils_info->fils_r_rk) - qdf_mem_free(fils_info->fils_r_rk); - if (fils_info->fils_r_ik) - qdf_mem_free(fils_info->fils_r_ik); + if (fils_info->fils_rrk) + qdf_mem_free(fils_info->fils_rrk); + if (fils_info->fils_rik) + qdf_mem_free(fils_info->fils_rik); if (fils_info->fils_eap_finish_pkt) qdf_mem_free(fils_info->fils_eap_finish_pkt); if (fils_info->fils_rmsk) @@ -338,8 +338,8 @@ static void pe_init_fils_info(tpPESession session) } fils_info->keyname_nai_data = NULL; fils_info->fils_erp_reauth_pkt = NULL; - fils_info->fils_r_rk = NULL; - fils_info->fils_r_ik = NULL; + fils_info->fils_rrk = NULL; + fils_info->fils_rik = NULL; fils_info->fils_eap_finish_pkt = NULL; fils_info->fils_rmsk = NULL; fils_info->fils_pmk = NULL; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index ce8e6acb5e60..56adc4bb0f40 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1005,6 +1005,8 @@ typedef struct tagCsrRoamProfile { bool do_not_roam; #ifdef WLAN_FEATURE_FILS_SK bool fils_connection; + uint8_t *hlp_ie; + uint32_t hlp_ie_len; struct cds_fils_connection_info *fils_con_info; #endif } tCsrRoamProfile; @@ -1457,7 +1459,13 @@ typedef struct tagCsrRoamInfo { uint8_t roamSynchInProgress; uint8_t synchAuthStatus; uint8_t kck[SIR_KCK_KEY_LEN]; - uint8_t kek[SIR_KEK_KEY_LEN]; + uint8_t kek[SIR_KEK_KEY_LEN_FILS]; + uint8_t kek_len; + uint32_t pmk_len; + uint8_t pmk[SIR_PMK_LEN]; + uint8_t pmkid[SIR_PMKID_LEN]; + bool update_erp_next_seq_num; + uint16_t next_erp_seq_num; uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; uint8_t subnet_change_status; #endif diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 12ea7d0ba501..b3e0c4e00d7d 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -860,7 +860,13 @@ typedef struct tagCsrRoamOffloadSynchStruct { struct qdf_mac_addr bssid; /* MAC address of roamed AP */ tCsrRoamOffloadAuthStatus authStatus; /* auth status */ uint8_t kck[SIR_KCK_KEY_LEN]; - uint8_t kek[SIR_KEK_KEY_LEN]; + uint8_t kek[SIR_KEK_KEY_LEN_FILS]; + uint32_t kek_len; + uint32_t pmk_len; + uint8_t pmk[SIR_PMK_LEN]; + uint8_t pmkid[SIR_PMKID_LEN]; + bool update_erp_next_seq_num; + uint16_t next_erp_seq_num; uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; tpSirBssDescription bss_desc_ptr; /*BSS descriptor*/ } csr_roam_offload_synch_params; diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 056b46fe499f..dcf73f8cd78f 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -330,6 +330,7 @@ void csr_roam_reset_roam_params(tpAniSirGlobal mac_ptr); #define REASON_ROAM_STOP_ALL 38 #define REASON_SUPPLICANT_DISABLED_ROAMING 39 #define REASON_CTX_INIT 40 +#define REASON_FILS_PARAMS_CHANGED 41 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) QDF_STATUS csr_roam_offload_scan(tpAniSirGlobal pMac, uint8_t sessionId, @@ -341,6 +342,22 @@ static inline QDF_STATUS csr_roam_offload_scan(tpAniSirGlobal pMac, return QDF_STATUS_E_NOSUPPORT; } #endif + +#if defined(WLAN_FEATURE_FILS_SK) +/** + * csr_update_fils_config - Update FILS config to CSR roam session + * @mac: MAC context + * @session_id: session id + * @src_profile: Source profile having latest FILS config + * + * API to update FILS config to roam csr session + * + * Return: QDF_STATUS + */ +QDF_STATUS csr_update_fils_config(tpAniSirGlobal mac, uint8_t session_id, + tCsrRoamProfile *src_profile); +#endif + QDF_STATUS csr_neighbor_roam_handoff_req_hdlr(tpAniSirGlobal pMac, void *pMsg); QDF_STATUS csr_neighbor_roam_proceed_with_handoff_req(tpAniSirGlobal pMac, uint8_t sessionId); diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 913f87f26de5..142eac9fecd1 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -355,7 +355,6 @@ QDF_STATUS sme_roam_set_pmkid_cache(tHalHandle hHal, uint8_t sessionId, tPmkidCacheInfo *pPMKIDCache, uint32_t numItems, bool update_entire_cache); - #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_STATUS sme_roam_set_psk_pmk(tHalHandle hHal, uint8_t sessionId, uint8_t *pPSK_PMK, size_t pmk_len); @@ -1808,4 +1807,64 @@ void sme_set_chan_info_callback(tHalHandle hal_handle, QDF_STATUS sme_set_bmiss_bcnt(uint32_t vdev_id, uint32_t first_cnt, uint32_t final_cnt); +/** + * sme_set_del_pmkid_cache() - API to update PMKID cache + * @hal: HAL handle for device + * @session_id: Session id + * @pmk_cache_info: Pointer to PMK cache info + * @is_add: boolean that implies whether to add or delete PMKID entry + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_set_del_pmkid_cache(tHalHandle hal, uint8_t session_id, + tPmkidCacheInfo *pmk_cache_info, + bool is_add); + +/** + * sme_send_hlp_ie_info() - API to send HLP IE info to fw + * @hal: HAL handle for device + * @session_id: Session id + * @profile: CSR Roam profile + * @if_addr: IP address + * + * This API is used to send HLP IE info along with IP address + * to fw if LFR3 is enabled. + * + * Return: QDF_STATUS + */ +void sme_send_hlp_ie_info(tHalHandle hal, uint8_t session_id, + tCsrRoamProfile *profile, uint32_t if_addr); + +#if defined(WLAN_FEATURE_FILS_SK) +/** + * sme_update_fils_config - Update FILS config to CSR roam session + * @hal: HAL handle for device + * @session_id: session id + * @src_profile: Source profile having latest FILS config + * + * API to update FILS config to roam csr session and update the same + * to fw if LFR3 is enabled. + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_update_fils_config(tHalHandle hal, uint8_t session_id, + tCsrRoamProfile *src_profile); + +/** + * sme_free_join_rsp_fils_params - free fils params + * @roam_info: roam info + * + * Return: void + */ +void sme_free_join_rsp_fils_params(tCsrRoamInfo *roam_info); +#else +static inline QDF_STATUS sme_update_fils_config(tHalHandle hal, + uint8_t session_id, + tCsrRoamProfile *src_profile) +{ + return QDF_STATUS_SUCCESS; +} +static inline void sme_free_join_rsp_fils_params(tCsrRoamInfo *roam_info) +{} +#endif #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 12b75df721f6..6741d6002732 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -6327,9 +6327,6 @@ QDF_STATUS sme_set_gtk_offload(tHalHandle hHal, *request_buf = *pGtkOffload; - if (pSession->is_fils_connection) - request_buf->ulFlags = GTK_OFFLOAD_DISABLE; - msg.type = WMA_GTK_OFFLOAD_REQ; msg.reserved = 0; msg.bodyptr = request_buf; @@ -8656,6 +8653,140 @@ QDF_STATUS sme_update_roam_rssi_diff(tHalHandle hHal, uint8_t sessionId, return status; } +#ifdef WLAN_FEATURE_FILS_SK +QDF_STATUS sme_update_fils_config(tHalHandle hal, uint8_t session_id, + tCsrRoamProfile *src_profile) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + QDF_STATUS status = QDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac->roam.neighborRoamInfo[session_id]; + + if (session_id >= CSR_ROAM_SESSION_MAX) { + sme_err("Invalid sme session id: %d", session_id); + return QDF_STATUS_E_INVAL; + } + + if (!src_profile) { + sme_err("src roam profile NULL"); + return QDF_STATUS_E_INVAL; + } + + if (!mac->roam.configParam.isFastRoamIniFeatureEnabled || + (neighbor_roam_info->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)) { + sme_info("Fast roam is disabled or not connected(%d)", + neighbor_roam_info->neighborRoamState); + return QDF_STATUS_E_PERM; + } + + csr_update_fils_config(mac, session_id, src_profile); + if (mac->roam.configParam.isRoamOffloadEnabled) { + sme_debug("Updating fils config to fw"); + csr_roam_offload_scan(mac, session_id, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_FILS_PARAMS_CHANGED); + } else { + sme_info("LFR3 not enabled"); + return QDF_STATUS_E_INVAL; + } + + return status; +} + +void sme_send_hlp_ie_info(tHalHandle hal, uint8_t session_id, + tCsrRoamProfile *profile, uint32_t if_addr) +{ + int i; + cds_msg_t msg; + QDF_STATUS status; + struct hlp_params *params; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id); + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac->roam.neighborRoamInfo[session_id]; + + if (!session) { + sme_err("session NULL"); + return; + } + + if (!mac->roam.configParam.isFastRoamIniFeatureEnabled || + (neighbor_roam_info->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)) { + sme_debug("Fast roam is disabled or not connected(%d)", + neighbor_roam_info->neighborRoamState); + return; + } + + params = qdf_mem_malloc(sizeof(*params)); + if (!params) { + sme_err("Mem alloc for HLP IE fails"); + return; + } + if ((profile->hlp_ie_len + + SIR_IPV4_ADDR_LEN) > FILS_MAX_HLP_DATA_LEN) { + sme_err("HLP IE len exceeds %d", + profile->hlp_ie_len); + qdf_mem_free(params); + return; + } + + params->vdev_id = session_id; + params->hlp_ie_len = profile->hlp_ie_len + SIR_IPV4_ADDR_LEN; + + for (i = 0; i < SIR_IPV4_ADDR_LEN; i++) + params->hlp_ie[i] = (if_addr >> (i * 8)) & 0xFF; + + qdf_mem_copy(params->hlp_ie + SIR_IPV4_ADDR_LEN, + profile->hlp_ie, profile->hlp_ie_len); + + msg.type = SIR_HAL_HLP_IE_INFO; + msg.reserved = 0; + msg.bodyptr = params; + status = sme_acquire_global_lock(&mac->sme); + if (status != QDF_STATUS_SUCCESS) { + sme_err("sme lock acquire fails"); + qdf_mem_free(params); + return; + } + + if (!QDF_IS_STATUS_SUCCESS + (cds_mq_post_message(QDF_MODULE_ID_WMA, &msg))) { + sme_err("Not able to post WMA_HLP_IE_INFO message to HAL"); + sme_release_global_lock(&mac->sme); + qdf_mem_free(params); + return; + } + + sme_release_global_lock(&mac->sme); +} + +void sme_free_join_rsp_fils_params(tCsrRoamInfo *roam_info) +{ + struct fils_join_rsp_params *roam_fils_params; + + if (!roam_info) + return; + + roam_fils_params = roam_info->fils_join_rsp; + if (!roam_fils_params) + return; + + if (roam_fils_params->fils_pmk) + qdf_mem_free(roam_fils_params->fils_pmk); + + qdf_mem_free(roam_fils_params); + + roam_info->fils_join_rsp = NULL; +} + +#else +inline void sme_send_hlp_ie_info(tHalHandle hal, uint8_t session_id, + tCsrRoamProfile *profile, uint32_t if_addr) +{} +#endif + /** * sme_update_fast_transition_enabled() - enable/disable Fast Transition * support at runtime @@ -17866,6 +17997,59 @@ QDF_STATUS sme_get_nud_debug_stats(tHalHandle hal, return QDF_STATUS_SUCCESS; } +QDF_STATUS sme_set_del_pmkid_cache(tHalHandle hal, uint8_t session_id, + tPmkidCacheInfo *pmk_cache_info, + bool is_add) +{ + wmi_pmk_cache *pmk_cache; + cds_msg_t msg; + + pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache)); + if (!pmk_cache) { + sme_err("Memory allocation failure"); + return QDF_STATUS_E_NOMEM; + } + + if (!pmk_cache_info->ssid_len) { + pmk_cache->cat_flag = WMI_PMK_CACHE_CAT_FLAG_BSSID; + WMI_CHAR_ARRAY_TO_MAC_ADDR(pmk_cache_info->BSSID.bytes, + &pmk_cache->bssid); + } else { + pmk_cache->cat_flag = WMI_PMK_CACHE_CAT_FLAG_SSID_CACHE_ID; + pmk_cache->ssid.ssid_len = pmk_cache_info->ssid_len; + qdf_mem_copy(pmk_cache->ssid.ssid, + pmk_cache_info->ssid, + pmk_cache->ssid.ssid_len); + } + pmk_cache->cache_id = (uint32_t) (pmk_cache_info->cache_id[0] << 8 | + pmk_cache_info->cache_id[1]); + + if (is_add) + pmk_cache->action_flag = WMI_PMK_CACHE_ACTION_FLAG_ADD_ENTRY; + else + pmk_cache->action_flag = WMI_PMK_CACHE_ACTION_FLAG_DEL_ENTRY; + + pmk_cache->pmkid_len = CSR_RSN_PMKID_SIZE; + qdf_mem_copy(pmk_cache->pmkid, pmk_cache_info->PMKID, + CSR_RSN_PMKID_SIZE); + + pmk_cache->pmk_len = pmk_cache_info->pmk_len; + qdf_mem_copy(pmk_cache->pmk, pmk_cache_info->pmk, + pmk_cache->pmk_len); + + msg.type = SIR_HAL_SET_DEL_PMKID_CACHE; + msg.reserved = session_id; + msg.bodyptr = pmk_cache; + if (QDF_STATUS_SUCCESS != + cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) { + sme_err("Not able to post message to WDA"); + qdf_mem_free(pmk_cache); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + /** * sme_delete_all_tdls_peers(): send request to delete tdls peers * @hal: handler for HAL diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 04121114b6f1..9da965bbbdfe 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3813,6 +3813,7 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId, EVENT_WLAN_STATUS_V2); } #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + return status; } @@ -7456,6 +7457,7 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, #endif csr_roam_link_up(mac_ctx, conn_profile->bssid); } + sme_free_join_rsp_fils_params(&roam_info); } /** @@ -7643,24 +7645,38 @@ static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, * * Return: None */ -static inline void update_profile_fils_info(tCsrRoamProfile *des_profile, +static void update_profile_fils_info(tCsrRoamProfile *des_profile, tCsrRoamProfile *src_profile) { - if (!src_profile->fils_con_info) + if (!src_profile || !src_profile->fils_con_info) return; - if (src_profile->fils_con_info->is_fils_connection) { - des_profile->fils_con_info = - qdf_mem_malloc(sizeof(struct cds_fils_connection_info)); - if (!des_profile->fils_con_info) { - sme_err("failed to allocate memory"); - return; - } + sme_debug("is fils %d", src_profile->fils_con_info->is_fils_connection); + + if (!src_profile->fils_con_info->is_fils_connection) + return; + + des_profile->fils_con_info = + qdf_mem_malloc(sizeof(struct cds_fils_connection_info)); + if (!des_profile->fils_con_info) { + sme_err("failed to allocate memory"); + return; + } - qdf_mem_copy(des_profile->fils_con_info, - src_profile->fils_con_info, - sizeof(struct cds_fils_connection_info)); + qdf_mem_copy(des_profile->fils_con_info, + src_profile->fils_con_info, + sizeof(struct cds_fils_connection_info)); + + des_profile->hlp_ie = + qdf_mem_malloc(src_profile->hlp_ie_len); + if (!des_profile->hlp_ie) { + sme_err("failed to allocate memory for hlp ie"); + return; } + + qdf_mem_copy(des_profile->hlp_ie, src_profile->hlp_ie, + src_profile->hlp_ie_len); + des_profile->hlp_ie_len = src_profile->hlp_ie_len; } #else static inline void update_profile_fils_info(tCsrRoamProfile *des_profile, @@ -10630,18 +10646,25 @@ static bool csr_create_fils_realm_hash(struct cds_fils_connection_info *fils_con_info, uint8_t *tmp_hash) { - uint8_t hash[SHA256_DIGEST_SIZE] = {0}; + uint8_t *hash; uint8_t *data[1]; if (!fils_con_info->realm_len) return false; + hash = qdf_mem_malloc(SHA256_DIGEST_SIZE); + if (!hash) { + sme_err("malloc fails in fils realm"); + return false; + } + data[0] = fils_con_info->realm; qdf_get_hash(SHA256_CRYPTO_TYPE, 1, data, &fils_con_info->realm_len, hash); qdf_trace_hex_dump(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, hash, SHA256_DIGEST_SIZE); qdf_mem_copy(tmp_hash, hash, 2); + qdf_mem_free(hash); return true; } @@ -18914,6 +18937,104 @@ csr_roam_offload_per_scan(tpAniSirGlobal mac_ctx, uint8_t session_id) return QDF_STATUS_SUCCESS; } +#if defined(WLAN_FEATURE_FILS_SK) +QDF_STATUS csr_update_fils_config(tpAniSirGlobal mac, uint8_t session_id, + tCsrRoamProfile *src_profile) +{ + tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id); + tCsrRoamProfile *dst_profile = NULL; + + if (!session) { + sme_err("session NULL"); + return QDF_STATUS_E_FAILURE; + } + + dst_profile = session->pCurRoamProfile; + + if (!dst_profile) { + sme_err("Current Roam profile of SME session NULL"); + return QDF_STATUS_E_FAILURE; + } + update_profile_fils_info(dst_profile, src_profile); + return QDF_STATUS_SUCCESS; +} + +/** + * copy_all_before_char() - API to copy all character before a particular char + * @str: Source string + * @dst: Destination string + * @c: Character before which all characters need to be copied + * + * Return: length of the copied string, if success. zero otherwise. + */ +static uint32_t copy_all_before_char(char *str, char *dst, char c) +{ + uint32_t len = 0; + + if (!str) + return len; + + while (*str != '\0' && *str != c) { + *dst++ = *str++; + len++; + } + return len; +} + +/** + * csr_update_fils_params_rso() - API to update FILS params in RSO + * @mac: Mac context + * @session: CSR Roam Session + * @req_buffer: RSO request buffer + * + * Return: None + */ +static void csr_update_fils_params_rso(tpAniSirGlobal mac, + tCsrRoamSession *session, tSirRoamOffloadScanReq *req_buffer) +{ + struct roam_fils_params *roam_fils_params; + struct cds_fils_connection_info *fils_info; + + if (!session->pCurRoamProfile) + return; + + fils_info = session->pCurRoamProfile->fils_con_info; + if (!fils_info || !req_buffer) + return; + + roam_fils_params = &req_buffer->roam_fils_params; + if ((fils_info->key_nai_length > FILS_MAX_KEYNAME_NAI_LENGTH) || + (fils_info->r_rk_length > FILS_MAX_RRK_LENGTH)) { + sme_err("Fils info len error: keyname nai len(%d) rrk len(%d)", + fils_info->key_nai_length, fils_info->r_rk_length); + return; + } + + req_buffer->is_fils_connection = true; + roam_fils_params->username_length = + copy_all_before_char(fils_info->keyname_nai, + roam_fils_params->username, '@'); + + roam_fils_params->next_erp_seq_num = + (fils_info->sequence_number + 1); + + roam_fils_params->rrk_length = fils_info->r_rk_length; + qdf_mem_copy(roam_fils_params->rrk, fils_info->r_rk, + roam_fils_params->rrk_length); + + /* REALM info */ + roam_fils_params->realm_len = fils_info->key_nai_length + - roam_fils_params->username_length - 1; + qdf_mem_copy(roam_fils_params->realm, fils_info->keyname_nai + + roam_fils_params->username_length + 1, + roam_fils_params->realm_len); +} +#else +static inline void csr_update_fils_params_rso(tpAniSirGlobal mac, + tCsrRoamSession *session, tSirRoamOffloadScanReq *req_buffer) +{} +#endif + /** * csr_roam_offload_scan() - populates roam offload scan request and sends to * WMA @@ -18976,13 +19097,6 @@ csr_roam_offload_scan(tpAniSirGlobal 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])) { - sme_info("Roaming not suppprted for fils based connection"); - 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 @@ -19129,6 +19243,7 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, session->pAddIEAssoc, session->nAddIEAssocLength); csr_update_driver_assoc_ies(mac_ctx, session, req_buf); + csr_update_fils_params_rso(mac_ctx, session, req_buf); } QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, @@ -20828,6 +20943,34 @@ void csr_roam_fill_tdls_info(tpAniSirGlobal mac_ctx, tCsrRoamInfo *roam_info, } #endif +#if defined(WLAN_FEATURE_FILS_SK) +static void csr_copy_fils_join_rsp_roam_info(tCsrRoamInfo *roam_info, + roam_offload_synch_ind *roam_synch_data) +{ + struct fils_join_rsp_params *roam_fils_info; + + roam_info->fils_join_rsp = qdf_mem_malloc(sizeof(*roam_fils_info)); + if (!roam_info->fils_join_rsp) { + sme_err("fils_join_rsp malloc fails!"); + return; + } + + roam_fils_info = roam_info->fils_join_rsp; + cds_copy_hlp_info(&roam_synch_data->dst_mac, + &roam_synch_data->src_mac, + roam_synch_data->hlp_data_len, + roam_synch_data->hlp_data, + &roam_fils_info->dst_mac, + &roam_fils_info->src_mac, + &roam_fils_info->hlp_data_len, + roam_fils_info->hlp_data); +} +#else +static inline void csr_copy_fils_join_rsp_roam_info(tCsrRoamInfo *roam_info, + roam_offload_synch_ind *roam_synch_data) +{} +#endif + #ifdef WLAN_FEATURE_ROAM_OFFLOAD static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, roam_offload_synch_ind *roam_synch_data, @@ -21134,14 +21277,29 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, } roam_info->roamSynchInProgress = true; roam_info->synchAuthStatus = roam_synch_data->authStatus; + 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->kek, roam_synch_data->kek, SIR_KEK_KEY_LEN); + qdf_mem_copy(roam_info->kek, roam_synch_data->kek, roam_info->kek_len); + + if (roam_synch_data->pmk_len) + qdf_mem_copy(roam_info->pmk, roam_synch_data->pmk, + roam_synch_data->pmk_len); + + qdf_mem_copy(roam_info->pmkid, roam_synch_data->pmkid, SIR_PMKID_LEN); + roam_info->update_erp_next_seq_num = + roam_synch_data->update_erp_next_seq_num; + roam_info->next_erp_seq_num = roam_synch_data->next_erp_seq_num; qdf_mem_copy(roam_info->replay_ctr, roam_synch_data->replay_ctr, SIR_REPLAY_CTR_LEN); QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, - FL("LFR3: Copy KCK, KEK and Replay Ctr")); + FL("LFR3: Copy KCK, KEK(len %d) and Replay Ctr"), + roam_info->kek_len); roam_info->subnet_change_status = CSR_GET_SUBNET_STATUS(roam_synch_data->roamReason); + + csr_copy_fils_join_rsp_roam_info(roam_info, roam_synch_data); + csr_roam_call_callback(mac_ctx, session_id, roam_info, 0, eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED); csr_reset_pmkid_candidate_list(mac_ctx, session_id); @@ -21158,6 +21316,7 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, session->fRoaming = false; session->roam_synch_in_progress = false; + sme_free_join_rsp_fils_params(roam_info); qdf_mem_free(roam_info->pbFrames); qdf_mem_free(roam_info); qdf_mem_free(ies_local); diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 9773d11f9e74..b238ee36fb36 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -5564,6 +5564,12 @@ static inline void csr_free_fils_profile_info(tCsrRoamProfile *profile) qdf_mem_free(profile->fils_con_info); profile->fils_con_info = NULL; } + + if (profile->hlp_ie) { + qdf_mem_free(profile->hlp_ie); + profile->hlp_ie = NULL; + profile->hlp_ie_len = 0; + } } #else static inline void csr_free_fils_profile_info(tCsrRoamProfile *profile) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index ba0c599af250..06c221362b81 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -6797,7 +6797,7 @@ static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id, qdf_mem_copy(offload_params.aKCK, params->aKCK, GTK_OFFLOAD_KCK_BYTES); qdf_mem_copy(offload_params.aKEK, params->aKEK, - GTK_OFFLOAD_KEK_BYTES); + params->kek_len); qdf_mem_copy(&offload_params.ullKeyReplayCounter, ¶ms->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES); } else { @@ -6806,6 +6806,7 @@ static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id, } enable_offload = params->ulFlags; + offload_params.kek_len = params->kek_len; /* send the wmi command */ status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle, diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 0dbcbf12136d..956431c25dd1 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -6678,6 +6678,32 @@ static void wma_get_arp_req_stats(WMA_HANDLE handle, } /** + * wma_set_del_pmkid_cache() - API to set/delete PMKID cache entry in fw + * @handle: WMA handle + * @pmk_cache: PMK cache entry + * @vdev_id: vdev id + * + * Return: None + */ +static void wma_set_del_pmkid_cache(WMA_HANDLE handle, + wmi_pmk_cache *pmk_cache, + uint32_t vdev_id) +{ + int status; + tp_wma_handle wma_handle = (tp_wma_handle) handle; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("WMA is closed, cannot send set del pmkid"); + return; + } + + status = wmi_unified_set_del_pmkid_cache(wma_handle->wmi_handle, + pmk_cache, vdev_id); + if (status != EOK) + WMA_LOGE("failed to send set/del pmkid cmd to fw"); +} + +/** * wma_process_action_frame_random_mac() - set/clear action frame random mac * @wma_handle: pointer to wma handle * @filter: pointer to buffer containing random mac, session_id and callback @@ -6955,6 +6981,46 @@ static QDF_STATUS wma_process_limit_off_chan(tp_wma_handle wma_handle, return QDF_STATUS_SUCCESS; } +#if defined(WLAN_FEATURE_FILS_SK) +/** + * wma_roam_scan_send_hlp() - API to send HLP IE info to fw + * @wma_handle: WMA handle + * @req: HLP params + * + * Return: QDF_STATUS + */ +static QDF_STATUS wma_roam_scan_send_hlp(tp_wma_handle wma_handle, + struct hlp_params *req) +{ + struct hlp_params *params; + QDF_STATUS status; + + params = qdf_mem_malloc(sizeof(*params)); + if (!params) { + WMA_LOGE("%s : Memory allocation failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + params->vdev_id = req->vdev_id; + params->hlp_ie_len = req->hlp_ie_len; + qdf_mem_copy(params->hlp_ie, req->hlp_ie, req->hlp_ie_len); + status = wmi_unified_roam_send_hlp_cmd(wma_handle->wmi_handle, params); + + WMA_LOGD("Send HLP status %d vdev id %d", status, params->vdev_id); + qdf_trace_hex_dump(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, + params->hlp_ie, 10); + + qdf_mem_free(params); + return status; +} +#else +static QDF_STATUS wma_roam_scan_send_hlp(tp_wma_handle wma_handle, + struct hlp_params *req) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * wma_mc_process_msg() - process wma messages and call appropriate function. * @cds_context: cds context @@ -7864,6 +7930,16 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) qdf_mem_free(msg->bodyptr); break; + case SIR_HAL_SET_DEL_PMKID_CACHE: + wma_set_del_pmkid_cache(wma_handle, + (wmi_pmk_cache *) msg->bodyptr, msg->reserved); + qdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_HLP_IE_INFO: + wma_roam_scan_send_hlp(wma_handle, + (struct hlp_params *)msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: WMA_LOGE("Unhandled WMA message of type %d", msg->type); if (msg->bodyptr) diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index ba44fdc46dba..cc6e3c7bd4b6 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -824,6 +824,58 @@ QDF_STATUS wma_roam_scan_mawc_params(tp_wma_handle wma_handle, return status; } +#ifdef WLAN_FEATURE_FILS_SK +/** + * wma_roam_scan_fill_fils_params() - API to fill FILS params in RSO command + * @wma_handle: WMA handle + * @params: Pointer to destination RSO params to be filled + * @roam_req: Pointer to RSO params from CSR + * + * Return: None + */ +static void wma_roam_scan_fill_fils_params(tp_wma_handle wma_handle, + struct roam_offload_scan_params + *params, tSirRoamOffloadScanReq + *roam_req) +{ + struct roam_fils_params *dst_fils_params, *src_fils_params; + + if (!params || !roam_req || !roam_req->is_fils_connection) { + WMA_LOGE("wma_roam_scan_fill_fils_params- NULL"); + return; + } + + src_fils_params = &roam_req->roam_fils_params; + dst_fils_params = ¶ms->roam_fils_params; + + params->add_fils_tlv = true; + + dst_fils_params->username_length = src_fils_params->username_length; + qdf_mem_copy(dst_fils_params->username, src_fils_params->username, + dst_fils_params->username_length); + + dst_fils_params->next_erp_seq_num = src_fils_params->next_erp_seq_num; + dst_fils_params->rrk_length = src_fils_params->rrk_length; + qdf_mem_copy(dst_fils_params->rrk, src_fils_params->rrk, + dst_fils_params->rrk_length); + + dst_fils_params->rik_length = src_fils_params->rik_length; + qdf_mem_copy(dst_fils_params->rik, src_fils_params->rik, + dst_fils_params->rik_length); + + dst_fils_params->realm_len = src_fils_params->realm_len; + qdf_mem_copy(dst_fils_params->realm, src_fils_params->realm, + dst_fils_params->realm_len); +} +#else +static inline void wma_roam_scan_fill_fils_params( + tp_wma_handle wma_handle, + struct roam_offload_scan_params *params, + tSirRoamOffloadScanReq *roam_req) + +{ } +#endif + /** * wma_roam_scan_offload_mode() - send roam scan mode request to fw * @wma_handle: wma handle @@ -893,6 +945,8 @@ QDF_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle, params->assoc_ie_length = roam_req->assoc_ie.length; qdf_mem_copy(params->assoc_ie, roam_req->assoc_ie.addIEdata, roam_req->assoc_ie.length); + + wma_roam_scan_fill_fils_params(wma_handle, params, roam_req); } WMA_LOGD(FL("qos_caps: %d, qos_enabled: %d, roam_scan_mode: %d"), @@ -1189,6 +1243,10 @@ A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype, return WMI_AUTH_OPEN; } return WMI_AUTH_NONE; + case eCSR_AUTH_TYPE_FILS_SHA256: + return WMI_AUTH_RSNA_FILS_SHA256; + case eCSR_AUTH_TYPE_FILS_SHA384: + return WMI_AUTH_RSNA_FILS_SHA384; default: return WMI_AUTH_NONE; } @@ -2106,6 +2164,7 @@ QDF_STATUS wma_process_roaming_config(tp_wma_handle wma_handle, roam_req->sessionId); if (qdf_status != QDF_STATUS_SUCCESS) break; + qdf_status = wma_roam_scan_filter(wma_handle, roam_req); if (qdf_status != QDF_STATUS_SUCCESS) { WMA_LOGE("Sending update for roam scan filter failed"); @@ -2292,6 +2351,7 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, uint8_t *reassoc_req_ptr; wmi_channel *chan; wmi_key_material *key; + wmi_roam_fils_synch_tlv_param *fils_info; synch_event = param_buf->fixed_param; roam_synch_ind_ptr->roamedVdevId = synch_event->vdev_id; @@ -2349,6 +2409,7 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, if (key != NULL) { qdf_mem_copy(roam_synch_ind_ptr->kck, key->kck, SIR_KCK_KEY_LEN); + roam_synch_ind_ptr->kek_len = SIR_KEK_KEY_LEN; qdf_mem_copy(roam_synch_ind_ptr->kek, key->kek, SIR_KEK_KEY_LEN); qdf_mem_copy(roam_synch_ind_ptr->replay_ctr, @@ -2371,6 +2432,35 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, else WMA_LOGD(FL("hw_mode transition fixed param is NULL")); + fils_info = (wmi_roam_fils_synch_tlv_param *) + (param_buf->roam_fils_synch_info); + if (param_buf->roam_fils_synch_info) { + roam_synch_ind_ptr->kek_len = fils_info->kek_len; + qdf_mem_copy(roam_synch_ind_ptr->kek, fils_info->kek, + fils_info->kek_len); + + roam_synch_ind_ptr->pmk_len = fils_info->pmk_len; + qdf_mem_copy(roam_synch_ind_ptr->pmk, fils_info->pmk, + fils_info->pmk_len); + + qdf_mem_copy(roam_synch_ind_ptr->pmkid, fils_info->pmkid, + SIR_PMKID_LEN); + + roam_synch_ind_ptr->update_erp_next_seq_num = + fils_info->update_erp_next_seq_num; + roam_synch_ind_ptr->next_erp_seq_num = + fils_info->next_erp_seq_num; + + WMA_LOGD("%s: KEK dump", __func__); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + roam_synch_ind_ptr->kek, fils_info->kek_len); + WMA_LOGD("%s: PMK dump", __func__); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + roam_synch_ind_ptr->pmk, fils_info->pmk_len); + WMA_LOGD("%s: PMKID dump", __func__); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + roam_synch_ind_ptr->pmkid, SIR_PMKID_LEN); + } return 0; } diff --git a/uapi/linux/qca_vendor.h b/uapi/linux/qca_vendor.h index 050b304205ca..3512ca43b215 100644 --- a/uapi/linux/qca_vendor.h +++ b/uapi/linux/qca_vendor.h @@ -2057,6 +2057,13 @@ enum qca_roaming_policy { * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK: KCK of the PTK * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK: KEK of the PTK * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS: subnet change status + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS: AUTH status from AP + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RETAIN_CONNECTION: old connection is + * retained + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK: AUTH PMK + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID: AUTH PMKID + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM: FILS erp next + * seq number */ enum qca_wlan_vendor_attr_roam_auth { QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0, @@ -2068,6 +2075,27 @@ enum qca_wlan_vendor_attr_roam_auth { QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS, + /* Indicates the status of re-association requested by user space for + * the BSSID specified by QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID. + * Type u16. + * Represents the status code from AP. Use + * %WLAN_STATUS_UNSPECIFIED_FAILURE if the device cannot give you the + * real status code for failures. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS, + /* This attribute indicates that the old association was maintained when + * a re-association is requested by user space and that re-association + * attempt fails (i.e., cannot connect to the requested BSS, but can + * remain associated with the BSS with which the association was in + * place when being requested to roam). Used along with + * WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS to indicate the current + * re-association status. Type flag. + * This attribute is applicable only for re-association failure cases. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RETAIN_CONNECTION, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1 |
