summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSridhar Selvaraj <sselvara@codeaurora.org>2017-08-07 16:43:30 +0530
committersnandini <snandini@codeaurora.org>2017-08-16 21:44:19 -0700
commit5d51228bcaa931c377fe1300dc9cc9710b68bf20 (patch)
tree83490d7c000864f97aa7f6d421a6a83f316eb2c0
parent7d3a7a22e0a3ac2e9dd20cef7854f30b2b2a7544 (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
-rw-r--r--core/cds/inc/cds_config.h2
-rw-r--r--core/hdd/inc/wlan_hdd_main.h17
-rw-r--r--core/hdd/src/wlan_hdd_assoc.c16
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c399
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h21
-rw-r--r--core/hdd/src/wlan_hdd_main.c53
-rw-r--r--core/hdd/src/wlan_hdd_power.c13
-rw-r--r--core/hdd/src/wlan_hdd_wext.c2
-rw-r--r--core/mac/inc/sir_api.h26
-rw-r--r--core/mac/src/include/sir_params.h2
-rw-r--r--core/mac/src/pe/include/lim_fils_defs.h18
-rw-r--r--core/mac/src/pe/include/lim_process_fils.h36
-rw-r--r--core/mac/src/pe/include/lim_session.h4
-rw-r--r--core/mac/src/pe/lim/lim_api.c44
-rw-r--r--core/mac/src/pe/lim/lim_process_fils.c157
-rw-r--r--core/mac/src/pe/lim/lim_process_sme_req_messages.c3
-rw-r--r--core/mac/src/pe/lim/lim_session.c12
-rw-r--r--core/sme/inc/csr_api.h10
-rw-r--r--core/sme/inc/csr_internal.h8
-rw-r--r--core/sme/inc/csr_neighbor_roam.h17
-rw-r--r--core/sme/inc/sme_api.h61
-rw-r--r--core/sme/src/common/sme_api.c190
-rw-r--r--core/sme/src/csr/csr_api_roam.c203
-rw-r--r--core/sme/src/csr/csr_util.c6
-rw-r--r--core/wma/src/wma_features.c3
-rw-r--r--core/wma/src/wma_main.c76
-rw-r--r--core/wma/src/wma_scan_roam.c90
-rw-r--r--uapi/linux/qca_vendor.h28
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,
&params->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 = &params->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