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
This commit is contained in:
Himanshu Agarwal 2018-04-06 17:39:37 +05:30 • committed by nshrivas
commit fc5d66088a
4 changed files with 33 additions and 8 deletions

View file

@ -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

View file

@ -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;

View file

@ -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));

View file

@ -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