Browse Source

qcacld-3.0: Use peer to get the cipher to decide MIC length

Driver uses cipher stored in vdev to get the MIC length, which
may get updated if multiple peer(TDLS peer in STA case) get
connected to the vdev. Thus depending on latest peer cipher type
the MIC length will be calculated for all peers.

Add changes to store cipher info in peer and use it to calculate
MIC length for the frame if CRYPTO_SET_KEY_CONVERGED is defined.

Change-Id: I852e4b519f55d8020237989314f8506aa275f379
CRs-Fixed: 2444416
Abhishek Singh 6 years ago
parent
commit
f880a7df25

+ 2 - 1
components/mlme/core/inc/wlan_mlme_main.h

@@ -127,6 +127,7 @@ mlme_vdev_object_destroyed_notification(struct wlan_objmgr_vdev *vdev,
 
 #endif
 
+#ifndef CRYPTO_SET_KEY_CONVERGED
 /**
  * wlan_peer_set_unicast_cipher() - set unicast cipher
  * @peer: PEER object
@@ -168,7 +169,7 @@ uint32_t wlan_peer_get_unicast_cipher(struct wlan_objmgr_peer *peer)
 
 	return peer_priv->ucast_key_cipher;
 }
-
+#endif
 /**
  * wma_get_peer_mic_len() - get mic hdr len and mic length for peer
  * @psoc: psoc

+ 57 - 0
components/mlme/core/src/wlan_mlme_main.c

@@ -26,6 +26,7 @@
 #include "wlan_scan_public_structs.h"
 #include "wlan_vdev_mlme_api.h"
 #include "wlan_mlme_api.h"
+#include <wlan_crypto_global_api.h>
 
 #define NUM_OF_SOUNDING_DIMENSIONS     1 /*Nss - 1, (Nss = 2 for 2x2)*/
 
@@ -239,6 +240,61 @@ out:
 	return status;
 }
 
+#ifdef CRYPTO_SET_KEY_CONVERGED
+QDF_STATUS mlme_get_peer_mic_len(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
+				 uint8_t *peer_mac, uint8_t *mic_len,
+				 uint8_t *mic_hdr_len)
+{
+	struct wlan_objmgr_peer *peer;
+	uint32_t key_cipher;
+
+	if (!psoc || !mic_len || !mic_hdr_len || !peer_mac) {
+		mlme_debug("psoc/mic_len/mic_hdr_len/peer_mac null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	peer = wlan_objmgr_get_peer(psoc, pdev_id,
+				    peer_mac, WLAN_LEGACY_MAC_ID);
+	if (!peer) {
+		mlme_debug("Peer of peer_mac %pM not found", peer_mac);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	key_cipher =
+		wlan_crypto_get_peer_param(peer,
+					   WLAN_CRYPTO_PARAM_UCAST_CIPHER);
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
+
+	if (key_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM) ||
+	    key_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM_256)) {
+		*mic_hdr_len = WLAN_IEEE80211_GCMP_HEADERLEN;
+		*mic_len = WLAN_IEEE80211_GCMP_MICLEN;
+	} else {
+		*mic_hdr_len = IEEE80211_CCMP_HEADERLEN;
+		*mic_len = IEEE80211_CCMP_MICLEN;
+	}
+	mlme_debug("peer %pM hdr_len %d mic_len %d key_cipher 0x%x", peer_mac,
+		   *mic_hdr_len, *mic_len, key_cipher);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+mlme_peer_object_created_notification(struct wlan_objmgr_peer *peer,
+				      void *arg)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+mlme_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
+					void *arg)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+#else
+
 QDF_STATUS mlme_get_peer_mic_len(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
 				 uint8_t *peer_mac, uint8_t *mic_len,
 				 uint8_t *mic_hdr_len)
@@ -334,6 +390,7 @@ mlme_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
 
 	return status;
 }
+#endif
 
 static void mlme_init_chainmask_cfg(struct wlan_objmgr_psoc *psoc,
 				    struct wlan_mlme_chainmask *chainmask_info)

+ 3 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -14834,6 +14834,9 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 	if (errno)
 		return errno;
 	cipher = osif_nl_to_crypto_cipher_type(params->cipher);
+	if (pairwise)
+		wma_set_peer_ucast_cipher(mac_address.bytes, cipher);
+
 	switch (adapter->device_mode) {
 	case QDF_IBSS_MODE:
 		errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index,

+ 11 - 0
core/wma/inc/wma.h

@@ -2558,6 +2558,17 @@ uint8_t wma_rx_invalid_peer_ind(uint8_t vdev_id, void *wh);
 struct wlan_objmgr_psoc *wma_get_psoc_from_scn_handle(void *scn_handle);
 
 #ifdef CRYPTO_SET_KEY_CONVERGED
+
+/**
+ * wma_set_peer_ucast_cipher() - Update unicast cipher fof the peer
+ * @mac_addr: peer mac address
+ * @cipher: peer cipher type
+ *
+ * Return: None
+ */
+void wma_set_peer_ucast_cipher(uint8_t *mac_addr,
+			       enum wlan_crypto_cipher_type cipher);
+
 /**
  * wma_update_set_key() - Update WMA layer for set key
  * @session_id: vdev session identifier

+ 53 - 3
core/wma/src/wma_features.c

@@ -5634,6 +5634,59 @@ static void wma_send_set_key_rsp(uint8_t session_id, bool pairwise,
 	}
 }
 
+static uint32_t wma_cipher_to_cap(enum wlan_crypto_cipher_type cipher)
+{
+	switch (cipher) {
+	case WLAN_CRYPTO_CIPHER_WEP:  return WLAN_CRYPTO_CAP_WEP;
+	case WLAN_CRYPTO_CIPHER_WEP_40:  return WLAN_CRYPTO_CAP_WEP;
+	case WLAN_CRYPTO_CIPHER_WEP_104:  return WLAN_CRYPTO_CAP_WEP;
+	case WLAN_CRYPTO_CIPHER_AES_OCB:  return WLAN_CRYPTO_CAP_AES;
+	case WLAN_CRYPTO_CIPHER_AES_CCM:  return WLAN_CRYPTO_CAP_AES;
+	case WLAN_CRYPTO_CIPHER_AES_CCM_256:  return WLAN_CRYPTO_CAP_AES;
+	case WLAN_CRYPTO_CIPHER_AES_GCM:  return WLAN_CRYPTO_CAP_AES;
+	case WLAN_CRYPTO_CIPHER_AES_GCM_256:  return WLAN_CRYPTO_CAP_AES;
+	case WLAN_CRYPTO_CIPHER_CKIP: return WLAN_CRYPTO_CAP_CKIP;
+	case WLAN_CRYPTO_CIPHER_TKIP: return WLAN_CRYPTO_CAP_TKIP_MIC;
+	case WLAN_CRYPTO_CIPHER_WAPI_SMS4: return WLAN_CRYPTO_CAP_WAPI_SMS4;
+	case WLAN_CRYPTO_CIPHER_WAPI_GCM4: return WLAN_CRYPTO_CAP_WAPI_GCM4;
+	case WLAN_CRYPTO_CIPHER_FILS_AEAD: return WLAN_CRYPTO_CAP_FILS_AEAD;
+	default: return 0;
+	}
+}
+
+void wma_set_peer_ucast_cipher(uint8_t *mac_addr,
+			       enum wlan_crypto_cipher_type cipher)
+{
+	int32_t set_val = 0, cipher_cap;
+	struct wlan_objmgr_peer *peer;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+	if (!wma) {
+		wma_err("wma context is NULL");
+		return;
+	}
+
+	peer = wlan_objmgr_get_peer(wma->psoc,
+				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
+				    mac_addr, WLAN_LEGACY_WMA_ID);
+	if (!peer) {
+		wma_err("Peer of peer_mac %pM not found", mac_addr);
+		return;
+	}
+	cipher_cap = wma_cipher_to_cap(cipher);
+	MLME_SET_BIT(set_val, cipher_cap);
+	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_CIPHER_CAP,
+				   set_val);
+	set_val = 0;
+	MLME_SET_BIT(set_val, cipher);
+	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
+				   set_val);
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
+
+	wma_debug("Set unicast cipher %x and cap %x for %pM", 1 << cipher,
+		  1 << cipher_cap, mac_addr);
+}
+
 static void wma_reset_ipn(struct wma_txrx_node *iface, uint8_t key_index)
 {
 	if (key_index == WMA_IGTK_KEY_INDEX_4 ||
@@ -5659,9 +5712,6 @@ void wma_update_set_key(uint8_t session_id, bool pairwise,
 		wma_info("iface not found for session id %d", session_id);
 
 	wma_reset_ipn(iface, key_index);
-	if (iface && pairwise)
-		iface->ucast_key_cipher =
-			wlan_crypto_cipher_to_wmi_cipher(cipher_type);
 	if (!pairwise && iface) {
 		/* Its GTK release the wake lock */
 		wma_debug("Release set key wake lock");

+ 79 - 10
core/wma/src/wma_scan_roam.c

@@ -75,6 +75,7 @@
 #include "wma_nan_datapath.h"
 #include "wlan_mlme_api.h"
 #include <wlan_mlme_main.h>
+#include <wlan_crypto_global_api.h>
 
 #ifdef FEATURE_WLAN_EXTSCAN
 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED
@@ -2467,8 +2468,71 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
 	return 0;
 }
 
+#ifdef CRYPTO_SET_KEY_CONVERGED
 static void wma_update_roamed_peer_unicast_cipher(tp_wma_handle wma,
 						  uint32_t uc_cipher,
+						  uint32_t cipher_cap,
+						  uint8_t *peer_mac)
+{
+	struct wlan_objmgr_peer *peer;
+
+	if (!peer_mac) {
+		wma_err("wma ctx or peer mac is NULL");
+		return;
+	}
+
+	peer = wlan_objmgr_get_peer(wma->psoc,
+				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
+				    peer_mac, WLAN_LEGACY_WMA_ID);
+	if (!peer) {
+		wma_err("Peer of peer_mac %pM not found", peer_mac);
+		return;
+	}
+	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_CIPHER_CAP,
+				   cipher_cap);
+	wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
+				   uc_cipher);
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
+
+	wma_debug("Set unicast cipher %x and cap %x for %pM", uc_cipher,
+		  cipher_cap, peer_mac);
+}
+
+static void wma_get_peer_uc_cipher(tp_wma_handle wma, uint8_t *peer_mac,
+				   uint32_t *uc_cipher, uint32_t *cipher_cap)
+{
+	uint32_t cipher, cap;
+	struct wlan_objmgr_peer *peer;
+
+	if (!peer_mac) {
+		WMA_LOGE("wma ctx or peer_mac is NULL");
+		return;
+	}
+	peer = wlan_objmgr_get_peer(wma->psoc,
+				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
+				    peer_mac, WLAN_LEGACY_WMA_ID);
+	if (!peer) {
+		WMA_LOGE("Peer of peer_mac %pM not found", peer_mac);
+		return;
+	}
+
+	cipher = wlan_crypto_get_peer_param(peer,
+					    WLAN_CRYPTO_PARAM_UCAST_CIPHER);
+	cap = wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_CIPHER_CAP);
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
+
+	if (uc_cipher)
+		*uc_cipher = cipher;
+	if (cipher_cap)
+		*cipher_cap = cap;
+}
+
+#else
+
+static void wma_update_roamed_peer_unicast_cipher(tp_wma_handle wma,
+						  uint32_t uc_cipher,
+						  uint32_t cipher_cap,
 						  uint8_t *peer_mac)
 {
 	struct wlan_objmgr_peer *peer;
@@ -2488,31 +2552,35 @@ static void wma_update_roamed_peer_unicast_cipher(tp_wma_handle wma,
 
 	wlan_peer_set_unicast_cipher(peer, uc_cipher);
 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
+
+	wma_debug("Set unicast cipher %d for %pM", uc_cipher, peer_mac);
 }
 
-static uint32_t wma_get_peer_uc_cipher(tp_wma_handle wma, uint8_t *peer_mac)
+static void wma_get_peer_uc_cipher(tp_wma_handle wma, uint8_t *peer_mac,
+				   uint32_t *uc_cipher, uint32_t *cipher_cap)
 {
-	uint32_t uc_cipher;
+	uint32_t cipher;
 	struct wlan_objmgr_peer *peer;
 
 	if (!peer_mac) {
 		WMA_LOGE("peer_mac is NULL");
-		return 0;
+		return;
 	}
 	peer = wlan_objmgr_get_peer(wma->psoc,
 				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
 				    peer_mac, WLAN_LEGACY_WMA_ID);
 	if (!peer) {
 		WMA_LOGE("Peer of peer_mac %pM not found", peer_mac);
-		return 0;
+		return;
 	}
 
-	uc_cipher = wlan_peer_get_unicast_cipher(peer);
+	cipher = wlan_peer_get_unicast_cipher(peer);
 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
 
-	return uc_cipher;
+	if (uc_cipher)
+		*uc_cipher = cipher;
 }
-
+#endif
 /**
  * wma_roam_update_vdev() - Update the STA and BSS
  * @wma: Global WMA Handle
@@ -2531,7 +2599,7 @@ static void wma_roam_update_vdev(tp_wma_handle wma,
 	tDeleteStaParams *del_sta_params;
 	tLinkStateParams *set_link_params;
 	tAddStaParams *add_sta_params;
-	uint32_t uc_cipher;
+	uint32_t uc_cipher = 0, cipher_cap = 0;
 	uint8_t vdev_id;
 
 	vdev_id = roam_synch_ind_ptr->roamed_vdev_id;
@@ -2569,13 +2637,14 @@ static void wma_roam_update_vdev(tp_wma_handle wma,
 	 * Get uc cipher of old peer to update new peer as it doesnt
 	 * change in roaming
 	 */
-	uc_cipher = wma_get_peer_uc_cipher(wma, del_bss_params->bssid);
+	wma_get_peer_uc_cipher(wma, del_bss_params->bssid, &uc_cipher,
+			       &cipher_cap);
 
 	wma_delete_sta(wma, del_sta_params);
 	wma_delete_bss(wma, del_bss_params);
 	wma_set_linkstate(wma, set_link_params);
 	/* Update new peer's uc cipher */
-	wma_update_roamed_peer_unicast_cipher(wma, uc_cipher,
+	wma_update_roamed_peer_unicast_cipher(wma, uc_cipher, cipher_cap,
 					      roam_synch_ind_ptr->bssid.bytes);
 	wma_add_bss(wma, (tpAddBssParams)roam_synch_ind_ptr->add_bss_params);
 	wma_add_sta(wma, add_sta_params);