Parcourir la source

qcacld-3.0: Send frames with GCMP MIC LEN if encryption is GCMP

CCMP and GCMP both have different lengths of their MIC part. MIC
length for CCMP is 8 bytes whereas it is 16 bytes for GCMP. When
encryption type is GCMP/GCMP-256, sending packets with CCMP MIC
length causes fw to drop the GCMP encrypted management packets
leading to connection issues.

Send GCMP encrypted frames with GCMP MIC length.

Change-Id: Ia83fa6ffde880fe69e5e4c3e3c3ce9c62ad8fa3c
CRs-Fixed: 2203224
Himanshu Agarwal il y a 7 ans
Parent
commit
fc5d66088a
4 fichiers modifiés avec 33 ajouts et 8 suppressions
  1. 3 1
      core/cds/inc/cds_ieee80211_common.h
  2. 2 0
      core/wma/inc/wma.h
  3. 12 3
      core/wma/src/wma_data.c
  4. 16 4
      core/wma/src/wma_mgmt.c

+ 3 - 1
core/cds/inc/cds_ieee80211_common.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011,2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011,2014-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1759,6 +1759,8 @@ enum {
 
 #define IEEE80211_CCMP_HEADERLEN    8
 #define IEEE80211_CCMP_MICLEN       8
+#define WLAN_IEEE80211_GCMP_HEADERLEN    8
+#define WLAN_IEEE80211_GCMP_MICLEN      16
 
 /*
  * 802.11w defines a MMIE chunk to be attached at the end of

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

@@ -925,6 +925,7 @@ typedef struct {
  * @key_length: key length
  * @key: key
  * @key_id: key id
+ * @key_cipher: key type
  */
 typedef struct {
 	uint16_t key_length;
@@ -1074,6 +1075,7 @@ struct wma_txrx_node {
 	uint8_t rmfEnabled;
 #ifdef WLAN_FEATURE_11W
 	wma_igtk_key_t key;
+	uint32_t ucast_key_cipher;
 #endif /* WLAN_FEATURE_11W */
 	uint32_t uapsd_cached_val;
 	tAniGetPEStatsRsp *stats_rsp;

+ 12 - 3
core/wma/src/wma_data.c

@@ -2425,11 +2425,20 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 		if (!IEEE80211_IS_BROADCAST(wh->i_addr1) &&
 		    !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 			if (pFc->wep) {
+				uint8_t mic_len, hdr_len;
+
 				/* Allocate extra bytes for privacy header and
 				 * trailer
 				 */
-				newFrmLen = frmLen + IEEE80211_CCMP_HEADERLEN +
-					    IEEE80211_CCMP_MICLEN;
+				if (iface->ucast_key_cipher ==
+				    WMI_CIPHER_AES_GCM) {
+					hdr_len = WLAN_IEEE80211_GCMP_HEADERLEN;
+					mic_len = WLAN_IEEE80211_GCMP_MICLEN;
+				} else {
+					hdr_len = IEEE80211_CCMP_HEADERLEN;
+					mic_len = IEEE80211_CCMP_MICLEN;
+				}
+				newFrmLen = frmLen + hdr_len + mic_len;
 				qdf_status =
 					cds_packet_alloc((uint16_t) newFrmLen,
 							 (void **)&pFrame,
@@ -2452,7 +2461,7 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 				qdf_mem_set(pFrame, newFrmLen, 0);
 				qdf_mem_copy(pFrame, wh, sizeof(*wh));
 				qdf_mem_copy(pFrame + sizeof(*wh) +
-					     IEEE80211_CCMP_HEADERLEN,
+					     hdr_len,
 					     pData + sizeof(*wh),
 					     frmLen - sizeof(*wh));
 

+ 16 - 4
core/wma/src/wma_mgmt.c

@@ -1781,10 +1781,11 @@ static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
 	params.key_len = key_params->key_len;
 
 #ifdef WLAN_FEATURE_11W
+	iface = &wma_handle->interfaces[key_params->vdev_id];
+
 	if ((key_params->key_type == eSIR_ED_AES_128_CMAC) ||
 	   (key_params->key_type == eSIR_ED_AES_GMAC_128) ||
 	   (key_params->key_type == eSIR_ED_AES_GMAC_256)) {
-		iface = &wma_handle->interfaces[key_params->vdev_id];
 		if (iface) {
 			iface->key.key_length = key_params->key_len;
 			iface->key.key_cipher = params.key_cipher;
@@ -1798,6 +1799,9 @@ static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
 					     CMAC_IPN_LEN);
 		}
 	}
+
+	if (key_params->unicast && iface)
+		iface->ucast_key_cipher = params.key_cipher;
 #endif /* WLAN_FEATURE_11W */
 
 	WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d",
@@ -3412,6 +3416,7 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle,
 {
 	uint8_t *orig_hdr;
 	uint8_t *ccmp;
+	uint8_t mic_len, hdr_len;
 
 	if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
 		if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
@@ -3431,15 +3436,22 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle,
 			return -EINVAL;
 		}
 
+		if (iface->ucast_key_cipher == WMI_CIPHER_AES_GCM) {
+			hdr_len = WLAN_IEEE80211_GCMP_HEADERLEN;
+			mic_len = WLAN_IEEE80211_GCMP_MICLEN;
+		} else {
+			hdr_len = IEEE80211_CCMP_HEADERLEN;
+			mic_len = IEEE80211_CCMP_MICLEN;
+		}
 		/* Strip privacy headers (and trailer)
 		 * for a received frame
 		 */
 		qdf_mem_move(orig_hdr +
-			IEEE80211_CCMP_HEADERLEN, wh,
+			hdr_len, wh,
 			sizeof(*wh));
 		qdf_nbuf_pull_head(wbuf,
-			IEEE80211_CCMP_HEADERLEN);
-		qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
+			hdr_len);
+		qdf_nbuf_trim_tail(wbuf, mic_len);
 		/*
 		 * CCMP header has been pulled off
 		 * reinitialize the start pointer of mac header