From fc5d66088a9c585712303d86bbedec48d0463a12 Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Fri, 6 Apr 2018 17:39:37 +0530 Subject: [PATCH] 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 --- core/cds/inc/cds_ieee80211_common.h | 4 +++- core/wma/inc/wma.h | 2 ++ core/wma/src/wma_data.c | 15 ++++++++++++--- core/wma/src/wma_mgmt.c | 20 ++++++++++++++++---- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/core/cds/inc/cds_ieee80211_common.h b/core/cds/inc/cds_ieee80211_common.h index 2c9f04f539fa..5a2ec1b26ad9 100644 --- a/core/cds/inc/cds_ieee80211_common.h +++ b/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 diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index c0a8962a3919..fde60c783a88 100644 --- a/core/wma/inc/wma.h +++ b/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; diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 5f1511b478f2..927f3576bffa 100644 --- a/core/wma/src/wma_data.c +++ b/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)); diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index e7163dca283c..3e3ea19da002 100644 --- a/core/wma/src/wma_mgmt.c +++ b/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