diff options
| author | Srinivas Girigowda <sgirigow@qca.qualcomm.com> | 2014-03-12 12:44:04 -0700 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-03-13 11:08:20 -0700 |
| commit | 2a5f89a556833ff242f49e240ca35db75b18ee84 (patch) | |
| tree | e774fda0601e2a059dcb3c0cd3c02dfa2d16aec1 | |
| parent | ce8d0dae57b83e259d35025ba1e81d88d5d6f569 (diff) | |
qcacld: Fix for PMF Broadcast frame IPN mismatch
The root cause of the problem is, on reception side of the group
addressed frame(s) keyID field in the MMIE is never used.
If the initial association uses key index of 4 for the iGTK
and AP sends broadcast DEAUTH/DISASSOC with KeyID 4 and incremental
value of IPN then driver correctly checks IPN and works accordingly.
But if the AP does broadcast key rotation and sends KeyID of 5 with
IPN less than last frame keyID=4 IPN, then driver thinks it is a
replay error and drops the frame, Hence link was not disconnected.
Fix for this issue is,
1. Both 4 and 5 are the valid KeyID's and hence maintain last
received frame IPN per KeyID (4 or 5).
2. On initial association, zero out the negotiated iGTK keyID's IPN
Change-Id: I4eeb148be55cee18ea6cb7117ab89a97161ec200
CRs-Fixed: 629266
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.c | 13 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 4 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.h | 16 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_utils.c | 4 |
4 files changed, 32 insertions, 5 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c index e147ca75d02b..0707159b12ec 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -418,6 +418,7 @@ static int tlshim_mgmt_rx_process(void *context, u_int8_t *data, struct wma_txrx_node *iface = NULL; tp_wma_handle wma; u_int8_t *efrm, *orig_hdr; + u_int16_t key_id; #endif /* WLAN_FEATURE_11W */ vos_pkt_t *rx_pkt; @@ -580,8 +581,18 @@ static int tlshim_mgmt_rx_process(void *context, u_int8_t *data, IEEE80211_IS_MULTICAST(wh->i_addr1)) { efrm = adf_nbuf_data(wbuf) + adf_nbuf_len(wbuf); + + key_id = (u_int16_t)*(efrm - vos_get_mmie_size() + 2); + if (!((key_id == WMA_IGTK_KEY_INDEX_4) || + (key_id == WMA_IGTK_KEY_INDEX_5))) { + TLSHIM_LOGE("Invalid KeyID(%d)" + " dropping the frame", key_id); + vos_pkt_return_packet(rx_pkt); + return 0; + } + if (vos_is_mmie_valid(iface->key.key, - iface->key.ipn, + iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, (u_int8_t *)wh, efrm)) { TLSHIM_LOGD("Protected BC/MC frame MMIE" diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 36a23de418c7..3ac974a12531 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -9189,6 +9189,10 @@ static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, vos_mem_copy (iface->key.key, (const void *) key_params->key_data, iface->key.key_length); + if ((cmd->key_ix == WMA_IGTK_KEY_INDEX_4) || + (cmd->key_ix == WMA_IGTK_KEY_INDEX_5)) + vos_mem_zero (iface->key.key_id[cmd->key_ix - WMA_IGTK_KEY_INDEX_4].ipn, + CMAC_IPN_LEN); } } #endif /* WLAN_FEATURE_11W */ diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 53ec297d94a9..e20dac5c15da 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -383,11 +383,23 @@ struct wma_wow { v_BOOL_t gtk_err_enable; }; #ifdef WLAN_FEATURE_11W -#define CMAC_IPN_LEN 6 +#define CMAC_IPN_LEN (6) +#define WMA_IGTK_KEY_INDEX_4 (4) +#define WMA_IGTK_KEY_INDEX_5 (5) + +typedef struct { + u_int8_t ipn[CMAC_IPN_LEN]; +} wma_igtk_ipn_t; + typedef struct { u_int16_t key_length; u_int8_t key[CSR_AES_KEY_LEN]; - u_int8_t ipn[CMAC_IPN_LEN]; + + /* IPN is maintained per iGTK keyID + * 0th index for iGTK keyID = 4; + * 1st index for iGTK KeyID = 5 + */ + wma_igtk_ipn_t key_id[2]; } wma_igtk_key_t; #endif diff --git a/CORE/VOSS/src/vos_utils.c b/CORE/VOSS/src/vos_utils.c index 1e6ac83fd15b..43d93099472f 100644 --- a/CORE/VOSS/src/vos_utils.c +++ b/CORE/VOSS/src/vos_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -221,7 +221,7 @@ v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn, { /* Replay error */ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - " mmie ipn %02X %02X %02X %02X %02X %02X" + "Replay error mmie ipn %02X %02X %02X %02X %02X %02X" " drvr ipn %02X %02X %02X %02X %02X %02X", rx_ipn[0], rx_ipn[1], rx_ipn[2], rx_ipn[3], rx_ipn[4], rx_ipn[5], ipn[0], ipn[1], ipn[2], ipn[3], ipn[4], ipn[5]); |
