Browse Source

qcacmn: Fix wep-shared in sta mode

Add selfpeer setting in obj manager
moved handling peer wep keys during peer obj creation
addressed wep encap issue, added trailer bits.
Wep key length check fixed

CRs-Fixed: 2090497
Change-Id: I0a409e12941270dd65fcffabcbee2d5d06cc1f06
Ashok Ponnaiah 7 years ago
parent
commit
b696221fd3

+ 74 - 32
umac/cmn_services/crypto/src/wlan_crypto_global_api.c

@@ -271,7 +271,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 	struct wlan_crypto_params *crypto_params;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_peer *peer;
-	struct wlan_crypto_key *key;
+	struct wlan_crypto_key *key = NULL;
 	const struct wlan_crypto_cipher *cipher;
 	uint8_t macaddr[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	bool isbcast;
@@ -313,10 +313,10 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 		qdf_print("%s[%d] cipher invalid\n", __func__, __LINE__);
 		return QDF_STATUS_E_INVAL;
 	} else if ((req_key->type == WLAN_CRYPTO_CIPHER_WEP) &&
-		!((req_key->keylen != WLAN_CRYPTO_KEY_WEP40_LEN)
-		|| (req_key->keylen != WLAN_CRYPTO_KEY_WEP104_LEN)
-		|| (req_key->keylen != WLAN_CRYPTO_KEY_WEP128_LEN))) {
-		qdf_print("%s[%d] cipher invalid\n", __func__, __LINE__);
+		!((req_key->keylen == WLAN_CRYPTO_KEY_WEP40_LEN)
+		|| (req_key->keylen == WLAN_CRYPTO_KEY_WEP104_LEN)
+		|| (req_key->keylen == WLAN_CRYPTO_KEY_WEP128_LEN))) {
+		qdf_print("%s[%d] wep key len invalid\n", __func__, __LINE__);
 		return QDF_STATUS_E_INVAL;
 	}
 
@@ -384,16 +384,23 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 		}
 		if (vdev_mode == QDF_STA_MODE) {
 			peer = wlan_vdev_get_bsspeer(vdev);
-			if (!peer) {
-				qdf_print("%s[%d] peer is null\n",
-							__func__, __LINE__);
+			if (!(peer && (QDF_STATUS_SUCCESS
+				== wlan_objmgr_peer_try_get_ref(peer,
+							WLAN_CRYPTO_ID)))) {
+				qdf_print("%s[%d] peer %p failed\n",
+						__func__, __LINE__, peer);
+				if (IS_MGMT_CIPHER(req_key->type)) {
+					crypto_priv->igtk_key = NULL;
+					crypto_priv->igtk_key_type
+						= WLAN_CRYPTO_CIPHER_NONE;
+				} else
+					crypto_priv->key[req_key->keyix] = NULL;
+				if (key)
+					qdf_mem_free(key);
 				return QDF_STATUS_E_INVAL;
 			}
-			wlan_objmgr_peer_try_get_ref(peer, WLAN_CRYPTO_ID);
-			wlan_peer_obj_lock(peer);
 			qdf_mem_copy(macaddr, wlan_peer_get_macaddr(peer),
 						WLAN_ALEN);
-			wlan_peer_obj_unlock(peer);
 			wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
 		}
 	} else {
@@ -643,7 +650,7 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev,
 	struct wlan_crypto_key *key;
 	struct wlan_crypto_cipher *cipher_table;
 	struct wlan_objmgr_psoc *psoc;
-	uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	uint8_t bssid_mac[WLAN_ALEN];
 
 	if (!vdev || !macaddr || (key_idx >= WLAN_CRYPTO_MAXKEYIDX)) {
 		qdf_print("%s[%d] Invalid params vdev %p, macaddr %p"
@@ -732,7 +739,7 @@ QDF_STATUS wlan_crypto_default_key(struct wlan_objmgr_vdev *vdev,
 	struct wlan_crypto_params *crypto_params;
 	struct wlan_crypto_key *key;
 	struct wlan_objmgr_psoc *psoc;
-	uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	uint8_t bssid_mac[WLAN_ALEN];
 
 	wlan_vdev_obj_lock(vdev);
 	qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
@@ -819,7 +826,7 @@ QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev,
 	QDF_STATUS status;
 	struct wlan_crypto_cipher *cipher_table;
 	struct wlan_objmgr_psoc *psoc;
-	uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	uint8_t bssid_mac[WLAN_ALEN];
 
 	if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf)))
 		return QDF_STATUS_E_INVAL;
@@ -902,7 +909,7 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev,
 	QDF_STATUS status;
 	struct wlan_crypto_cipher *cipher_table;
 	struct wlan_objmgr_psoc *psoc;
-	uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	uint8_t bssid_mac[WLAN_ALEN];
 
 	if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf)))
 		return QDF_STATUS_E_INVAL;
@@ -984,7 +991,7 @@ QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
 	QDF_STATUS status;
 	struct wlan_crypto_cipher *cipher_table;
 	struct wlan_objmgr_psoc *psoc;
-	uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	uint8_t bssid_mac[WLAN_ALEN];
 
 	wlan_vdev_obj_lock(vdev);
 	qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
@@ -1065,7 +1072,7 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
 	QDF_STATUS status;
 	struct wlan_crypto_cipher *cipher_table;
 	struct wlan_objmgr_psoc *psoc;
-	uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	uint8_t bssid_mac[WLAN_ALEN];
 
 	wlan_vdev_obj_lock(vdev);
 	qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
@@ -2392,11 +2399,13 @@ QDF_STATUS wlan_crypto_set_peer_wep_keys(struct wlan_objmgr_vdev *vdev,
 						uint8_t *mac_addr){
 	uint8_t keymac[WLAN_ALEN];
 	struct wlan_crypto_comp_priv *crypto_priv;
+	struct wlan_crypto_comp_priv *sta_crypto_priv;
 	struct wlan_crypto_params *crypto_params;
 	struct wlan_crypto_key *key;
-	struct wlan_crypto_key *tmp_key;
+	struct wlan_crypto_key *sta_key;
 	struct wlan_crypto_cipher *cipher_table;
 	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_peer *peer;
 	int i;
 	enum tQDF_ADAPTER_MODE opmode;
 
@@ -2424,14 +2433,37 @@ QDF_STATUS wlan_crypto_set_peer_wep_keys(struct wlan_objmgr_vdev *vdev,
 	if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr))
 		return QDF_STATUS_E_INVAL;
 
-	tmp_key = (struct wlan_crypto_key *)qdf_mem_malloc(
-					sizeof(struct wlan_crypto_key));
+	if (opmode == QDF_STA_MODE) {
+		peer = wlan_vdev_get_bsspeer(vdev);
+		if (!(peer && (QDF_STATUS_SUCCESS
+			== wlan_objmgr_peer_try_get_ref(peer,
+						WLAN_CRYPTO_ID)))) {
+			qdf_print("%s[%d] peer %p ref failed\n",
+						__func__, __LINE__, peer);
+			return QDF_STATUS_E_INVAL;
+		}
+	} else {
+		uint8_t bssid_mac[WLAN_ALEN];
 
-	if (!tmp_key)
-		return QDF_STATUS_E_NULL_VALUE;
+		wlan_vdev_obj_lock(vdev);
+		qdf_mem_copy(bssid_mac,
+				wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
+		wlan_vdev_obj_unlock(vdev);
 
+		peer = wlan_objmgr_get_peer_by_mac_n_vdev(
+				psoc, mac_addr, bssid_mac, WLAN_CRYPTO_ID);
+		if (!peer) {
+			qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
+			return QDF_STATUS_E_INVAL;
+		}
+	}
 
-	/* push only valid static WEP keys from vap */
+	wlan_crypto_peer_get_comp_params(peer, &sta_crypto_priv);
+	wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
+	if (sta_crypto_priv == NULL) {
+		qdf_print("%s[%d] sta priv is null\n", __func__, __LINE__);
+		return QDF_STATUS_E_INVAL;
+	}
 
 	for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
 		if (crypto_priv->key[i]) {
@@ -2443,37 +2475,47 @@ QDF_STATUS wlan_crypto_set_peer_wep_keys(struct wlan_objmgr_vdev *vdev,
 							key->cipher_table;
 
 			if (cipher_table->cipher == WLAN_CRYPTO_CIPHER_WEP) {
-				qdf_mem_copy(tmp_key, key,
+				sta_key = qdf_mem_malloc(
+						sizeof(struct wlan_crypto_key));
+				if (!sta_key) {
+					qdf_print("%s[%d] key alloc failed\n",
+							__func__, __LINE__);
+					return QDF_STATUS_E_NOMEM;
+				}
+				sta_crypto_priv->key[i] = sta_key;
+				qdf_mem_copy(sta_key, key,
 						sizeof(struct wlan_crypto_key));
 				qdf_copy_macaddr((struct qdf_mac_addr *)keymac,
 					(struct qdf_mac_addr *)mac_addr);
 
-				tmp_key->flags &= ~WLAN_CRYPTO_KEY_DEFAULT;
-				if (crypto_priv->def_tx_keyid == i)
-					tmp_key->flags
-						|= WLAN_CRYPTO_KEY_DEFAULT;
+				sta_key->flags &= ~WLAN_CRYPTO_KEY_DEFAULT;
 
+				if (crypto_priv->def_tx_keyid == i) {
+					sta_key->flags
+						|= WLAN_CRYPTO_KEY_DEFAULT;
+					sta_crypto_priv->def_tx_keyid =
+						crypto_priv->def_tx_keyid;
+				}
 				/* setting the broadcast/multicast key for sta*/
 				if (opmode == QDF_STA_MODE ||
 						opmode == QDF_IBSS_MODE){
 					if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
 						WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(
-							vdev, tmp_key, mac_addr,
+							vdev, sta_key, mac_addr,
 							cipher_table->cipher);
 					}
 				}
 
 				/* setting unicast key */
-				tmp_key->flags &= ~WLAN_CRYPTO_KEY_GROUP;
+				sta_key->flags &= ~WLAN_CRYPTO_KEY_GROUP;
 				if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
 					WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev,
-						tmp_key, mac_addr,
+						sta_key, mac_addr,
 						cipher_table->cipher);
 				}
 			}
 		}
 	}
-	qdf_mem_free(tmp_key);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 27 - 5
umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c

@@ -30,6 +30,7 @@
 #include <wlan_objmgr_peer_obj.h>
 
 #include "wlan_crypto_global_def.h"
+#include "wlan_crypto_global_api.h"
 #include "wlan_crypto_def_i.h"
 #include "wlan_crypto_main_i.h"
 #include "wlan_crypto_obj_mgr_i.h"
@@ -97,6 +98,7 @@ static QDF_STATUS wlan_crypto_vdev_obj_create_handler(
 	struct wlan_crypto_comp_priv *crypto_priv;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_crypto_params *crypto_param;
+	QDF_STATUS status;
 
 	if (!vdev)
 		return QDF_STATUS_E_INVAL;
@@ -127,10 +129,14 @@ static QDF_STATUS wlan_crypto_vdev_obj_create_handler(
 	/* update the fw_caps into ciphercaps then attach to objmgr*/
 	wlan_crypto_register_all_ciphers(crypto_param);
 
-	return wlan_objmgr_vdev_component_obj_attach(vdev,
+	status = wlan_objmgr_vdev_component_obj_attach(vdev,
 							WLAN_UMAC_COMP_CRYPTO,
 							(void *)crypto_priv,
 							QDF_STATUS_SUCCESS);
+	if (status != QDF_STATUS_SUCCESS)
+		qdf_mem_free(crypto_priv);
+
+	return status;
 }
 
 static QDF_STATUS wlan_crypto_peer_obj_create_handler(
@@ -138,6 +144,8 @@ static QDF_STATUS wlan_crypto_peer_obj_create_handler(
 						void *arg)
 {
 	struct wlan_crypto_comp_priv *crypto_priv;
+	uint8_t keymac[WLAN_ALEN];
+	QDF_STATUS status;
 
 	if (!peer)
 		return QDF_STATUS_E_INVAL;
@@ -146,10 +154,24 @@ static QDF_STATUS wlan_crypto_peer_obj_create_handler(
 	if (!crypto_priv)
 		return QDF_STATUS_E_NOMEM;
 
-	return wlan_objmgr_peer_component_obj_attach(peer,
-							WLAN_UMAC_COMP_CRYPTO,
-							(void *)crypto_priv,
-							QDF_STATUS_SUCCESS);
+	status = wlan_objmgr_peer_component_obj_attach(peer,
+				WLAN_UMAC_COMP_CRYPTO, (void *)crypto_priv,
+				QDF_STATUS_SUCCESS);
+
+	if (status == QDF_STATUS_SUCCESS) {
+		if (wlan_vdev_get_selfpeer(peer->peer_objmgr.vdev) != peer) {
+			qdf_copy_macaddr((struct qdf_mac_addr *)keymac,
+			(struct qdf_mac_addr *)wlan_peer_get_macaddr(peer));
+			wlan_crypto_set_peer_wep_keys(
+					wlan_peer_get_vdev(peer), keymac);
+		}
+	} else {
+		qdf_print("%s[%d] peer obj failed status %d\n",
+					__func__, __LINE__, status);
+		qdf_mem_free(crypto_priv);
+	}
+
+	return status;
 }
 
 static QDF_STATUS wlan_crypto_psoc_obj_destroy_handler(

+ 12 - 3
umac/cmn_services/crypto/src/wlan_crypto_wep.c

@@ -56,12 +56,21 @@ static QDF_STATUS wep_encap(struct wlan_crypto_key *key,
 		ivp = (uint8_t *)qdf_nbuf_data(wbuf);
 	} else {
 		ivp = (uint8_t *)qdf_nbuf_push_head(wbuf,
-						cipher_table->header);
-		memmove(ivp, ivp + cipher_table->header, hdrlen);
+						cipher_table->header
+						+ cipher_table->trailer);
+		qdf_mem_move(ivp,
+			ivp + cipher_table->header + cipher_table->trailer,
+			hdrlen);
+		qdf_mem_move(ivp + hdrlen + cipher_table->header,
+			ivp + hdrlen
+			+ cipher_table->header + cipher_table->trailer,
+			(qdf_nbuf_len(wbuf) - hdrlen
+			- cipher_table->header + cipher_table->trailer));
+		ivp = (uint8_t *)qdf_nbuf_data(wbuf);
 	}
 
 	ivp += hdrlen;
-
+	key->keytsc++;
 #if _BYTE_ORDER == _BIG_ENDIAN
 	ivp[2] = key->keyrsc[0] >> 0;
 	ivp[1] = key->keyrsc[0] >> 8;

+ 16 - 16
umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c

@@ -614,24 +614,24 @@ QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
 	objmgr->wlan_peer_count++;
 	wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
 
-	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
-	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) {
-		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
-				 wlan_vdev_mlme_get_macaddr(vdev)) ==
-					QDF_STATUS_SUCCESS) {
-			/*
-			 * if peer mac address and vdev mac address match, set
-			 * this peer as self peer
-			 */
-			wlan_vdev_set_selfpeer(vdev, peer);
-			/* For AP mode, self peer and BSS peer are same */
-			if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
-				wlan_vdev_set_bsspeer(vdev, peer);
-		}
-		/* set BSS peer for sta */
-		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
+	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
+			 wlan_vdev_mlme_get_macaddr(vdev)) ==
+				QDF_STATUS_SUCCESS) {
+		/*
+		 * if peer mac address and vdev mac address match, set
+		 * this peer as self peer
+		 */
+		wlan_vdev_set_selfpeer(vdev, peer);
+		/* For AP mode, self peer and BSS peer are same */
+		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
 			wlan_vdev_set_bsspeer(vdev, peer);
 	}
+	/* set BSS peer for sta */
+	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
+		((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
+		 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)))
+		wlan_vdev_set_bsspeer(vdev, peer);
+
 	/* Increment vdev ref count to make sure it won't be destroyed before */
 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
 	wlan_vdev_obj_unlock(vdev);