qcacld-3.0: Use crypto API to fill and validate mmie

Use crypto API to fill and validate mmie for BC frames.

Change-Id: Ibe420f974c1f8fb3796168e6db976061f904d520
CRs-Fixed: 2664276
This commit is contained in:
Abhishek Singh 2020-04-09 17:21:44 +05:30 committed by nshrivas
parent 405d82a9cb
commit 3f29b6c7f2
8 changed files with 33 additions and 697 deletions

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2014-2016 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
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#if !defined(__CDS_CRYPTO_H)
#define __CDS_CRYPTO_H
/**
* DOC: cds_crypto.h
*
* Crypto APIs
*
*/
#include <linux/crypto.h>
static inline struct crypto_cipher *
cds_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask)
{
return crypto_alloc_cipher(alg_name, type, mask);
}
static inline void cds_crypto_free_cipher(struct crypto_cipher *tfm)
{
crypto_free_cipher(tfm);
}
#endif /* if !defined __CDS_CRYPTO_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2020 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
@ -101,23 +101,7 @@ uint8_t cds_freq_to_chan(uint32_t freq);
enum cds_band_type cds_chan_to_band(uint32_t chan);
#ifdef WLAN_FEATURE_11W
bool cds_is_mmie_valid(uint8_t *key, uint8_t *ipn,
uint8_t *frm, uint8_t *efrm);
bool cds_attach_mmie(uint8_t *igtk, uint8_t *ipn, uint16_t key_id,
uint8_t *frm, uint8_t *efrm, uint16_t frmLen);
uint8_t cds_get_mmie_size(void);
/**
* cds_is_gmac_mmie_valid: Validates GMAC MIC
* @igtk: integrity group temporal key
* @ipn: IGTK packet number
* @frm: IEEE 802.11 frame
* @efrm: End of frame
* @key_length: Length of IGTK
*
* Return: True if MIC validation is successful, false otherwise
*/
bool cds_is_gmac_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm,
uint8_t *efrm, uint16_t key_length);
/**
* cds_get_gmac_mmie_size: Gives length of GMAC MMIE size

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2020 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
@ -40,8 +40,6 @@
#include "qdf_trace.h"
#include "cds_utils.h"
#include "qdf_mem.h"
#include "cds_crypto.h"
#include <linux/err.h>
#include <linux/random.h>
#include <linux/crypto.h>
@ -57,10 +55,6 @@
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
#define AAD_LEN 20
#define CMAC_IPN_LEN 6
#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
#define GMAC_NONCE_LEN 12
/*----------------------------------------------------------------------------
* Type Declarations
@ -75,111 +69,6 @@
/*----------------------------------------------------------------------------
Function Definitions and Documentation
* -------------------------------------------------------------------------*/
#ifdef WLAN_FEATURE_11W
static inline void xor_128(const u8 *a, const u8 *b, u8 *out)
{
u8 i;
for (i = 0; i < AES_BLOCK_SIZE; i++)
out[i] = a[i] ^ b[i];
}
static inline void leftshift_onebit(const u8 *input, u8 *output)
{
int i, overflow = 0;
for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) {
output[i] = input[i] << 1;
output[i] |= overflow;
overflow = (input[i] & 0x80) ? 1 : 0;
}
return;
}
static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2)
{
u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
u8 const_rb[AES_BLOCK_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
};
u8 const_zero[AES_BLOCK_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
crypto_cipher_encrypt_one(tfm, l, const_zero);
if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
leftshift_onebit(l, k1);
} else { /* Else k1 = ( l << 1 ) (+) Rb */
leftshift_onebit(l, tmp);
xor_128(tmp, const_rb, k1);
}
if ((k1[0] & 0x80) == 0) {
leftshift_onebit(k1, k2);
} else {
leftshift_onebit(k1, tmp);
xor_128(tmp, const_rb, k2);
}
}
static inline void padding(u8 *lastb, u8 *pad, u16 length)
{
u8 j;
/* original last block */
for (j = 0; j < AES_BLOCK_SIZE; j++) {
if (j < length)
pad[j] = lastb[j];
else if (j == length)
pad[j] = 0x80;
else
pad[j] = 0x00;
}
}
static void cds_cmac_calc_mic(struct crypto_cipher *tfm,
u8 *m, u16 length, u8 *mac)
{
u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
int cmpBlk;
int i, nBlocks = (length + 15) / AES_BLOCK_SIZE;
generate_subkey(tfm, k1, k2);
if (nBlocks == 0) {
nBlocks = 1;
cmpBlk = 0;
} else {
cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0;
}
if (cmpBlk) { /* Last block is complete block */
xor_128(&m[AES_BLOCK_SIZE * (nBlocks - 1)], k1, m_last);
} else { /* Last block is not complete block */
padding(&m[AES_BLOCK_SIZE * (nBlocks - 1)], padded,
length % AES_BLOCK_SIZE);
xor_128(padded, k2, m_last);
}
for (i = 0; i < AES_BLOCK_SIZE; i++)
x[i] = 0;
for (i = 0; i < (nBlocks - 1); i++) {
xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */
crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */
}
xor_128(x, m_last, y);
crypto_cipher_encrypt_one(tfm, x, y);
memcpy(mac, x, CMAC_TLEN);
}
#endif
#ifdef WLAN_FEATURE_11W
uint8_t cds_get_mmie_size(void)
@ -187,279 +76,6 @@ uint8_t cds_get_mmie_size(void)
return sizeof(struct ieee80211_mmie);
}
/*--------------------------------------------------------------------------
\brief cds_increase_seq() - Increase the IPN aka Sequence number by one unit
The cds_increase_seq() function increases the IPN by one unit.
\param ipn - pointer to the IPN aka Sequence number [6 bytes]
--------------------------------------------------------------------------*/
static void cds_increase_seq(uint8_t *ipn)
{
uint64_t value = 0;
if (ipn) {
value = (0xffffffffffff) & (*((uint64_t *) ipn));
value = value + 1;
qdf_mem_copy(ipn, &value, IEEE80211_MMIE_IPNLEN);
}
}
/*--------------------------------------------------------------------------
\brief cds_attach_mmie() - attches the complete MMIE at the end of frame
The cds_attach_mmie() calculates the entire MMIE and attaches at the end
of Broadcast/Multicast robust management frames.
\param igtk - pointer group key which will be used to calculate
the 8 byte MIC.
\param ipn - pointer ipn, it is also known as sequence number
\param key_id - key identication number
\param frm - pointer to the start of the frame.
\param efrm - pointer to the end of the frame.
\param frmLen - size of the entire frame.
\return - this function will return true on success and false on
failure.
--------------------------------------------------------------------------*/
bool
cds_attach_mmie(uint8_t *igtk, uint8_t *ipn, uint16_t key_id,
uint8_t *frm, uint8_t *efrm, uint16_t frmLen)
{
struct ieee80211_mmie *mmie;
struct ieee80211_frame *wh;
uint8_t aad[AAD_LEN], mic[CMAC_TLEN], *input = NULL;
uint8_t previous_ipn[IEEE80211_MMIE_IPNLEN] = { 0 };
uint16_t nBytes = 0;
int ret = 0;
struct crypto_cipher *tfm;
/* This is how received frame look like
*
* <------------frmLen---------------------------->
*
* +---------------+----------------------+-------+
* | 802.11 HEADER | Management framebody | MMIE |
* +---------------+----------------------+-------+
* ^
* |
* efrm
* This is how MMIE from above frame look like
*
*
* <------------ 18 Bytes----------------------------->
* +--------+---------+---------+-----------+---------+
* |Element | Length | Key id | IPN | MIC |
* | id | | | | |
* +--------+---------+---------+-----------+---------+
* Octet 1 1 2 6 8
*
*/
/* Check if frame is invalid length */
if (((efrm - frm) != frmLen) || (frmLen < sizeof(*wh))) {
cds_err("Invalid frame length");
return false;
}
mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));
/* Copy Element id */
mmie->element_id = WLAN_ELEMID_MMIE;
/* Copy Length */
mmie->length = sizeof(*mmie) - 2;
/* Copy Key id */
mmie->key_id = key_id;
/*
* In case of error, revert back to original IPN
* to do that copy the original IPN into previous_ipn
*/
qdf_mem_copy(&previous_ipn[0], ipn, IEEE80211_MMIE_IPNLEN);
cds_increase_seq(ipn);
qdf_mem_copy(mmie->sequence_number, ipn, IEEE80211_MMIE_IPNLEN);
/*
* Calculate MIC and then copy
*/
tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
ret = PTR_ERR(tfm);
tfm = NULL;
cds_err("crypto_alloc_cipher failed (%d)", ret);
goto err_tfm;
}
ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
if (ret) {
cds_err("crypto_cipher_setkey failed (%d)", ret);
goto err_tfm;
}
/* Construct AAD */
wh = (struct ieee80211_frame *)frm;
/* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */
/* FC type/subtype */
aad[0] = wh->i_fc[0];
/* Mask FC Retry, PwrMgt, MoreData flags to zero */
aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
IEEE80211_FC1_MORE_DATA);
/* A1 || A2 || A3 */
qdf_mem_copy(aad + 2, wh->i_addr_all, 3 * QDF_MAC_ADDR_SIZE);
/* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
nBytes = AAD_LEN + (frmLen - sizeof(struct ieee80211_frame));
input = (uint8_t *) qdf_mem_malloc(nBytes);
if (!input) {
cds_err("Memory allocation failed");
ret = QDF_STATUS_E_NOMEM;
goto err_tfm;
}
/*
* Copy the AAD, Management frame body, and
* MMIE with 8 bit MIC zeroed out
*/
qdf_mem_copy(input, aad, AAD_LEN);
/* Copy Management Frame Body and MMIE without MIC */
qdf_mem_copy(input + AAD_LEN,
(uint8_t *) (efrm -
(frmLen - sizeof(struct ieee80211_frame))),
nBytes - AAD_LEN - CMAC_TLEN);
cds_cmac_calc_mic(tfm, input, nBytes, mic);
qdf_mem_free(input);
cds_debug("CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
mic[0], mic[1], mic[2], mic[3],
mic[4], mic[5], mic[6], mic[7]);
qdf_mem_copy(mmie->mic, mic, IEEE80211_MMIE_MICLEN);
err_tfm:
if (ret) {
qdf_mem_copy(ipn, previous_ipn, IEEE80211_MMIE_IPNLEN);
}
if (tfm)
cds_crypto_free_cipher(tfm);
return !ret ? true : false;
}
bool
cds_is_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm, uint8_t *efrm)
{
struct ieee80211_mmie *mmie;
struct ieee80211_frame *wh;
uint8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input;
uint16_t nBytes = 0;
int ret = 0;
struct crypto_cipher *tfm;
/* Check if frame is invalid length */
if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) {
cds_err("Invalid frame length");
return false;
}
mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));
/* Check Element ID */
if ((mmie->element_id != WLAN_ELEMID_MMIE) ||
(mmie->length != (sizeof(*mmie) - 2))) {
cds_err("IE is not Mgmt MIC IE or Invalid length");
/* IE is not Mgmt MIC IE or invalid length */
return false;
}
/* Validate IPN */
rx_ipn = mmie->sequence_number;
if (qdf_mem_cmp(rx_ipn, ipn, CMAC_IPN_LEN) <= 0) {
/* Replay error */
cds_err("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]);
return false;
}
tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
ret = PTR_ERR(tfm);
tfm = NULL;
cds_err("crypto_alloc_cipher failed (%d)", ret);
goto err_tfm;
}
ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
if (ret) {
cds_err("crypto_cipher_setkey failed (%d)", ret);
goto err_tfm;
}
/* Construct AAD */
wh = (struct ieee80211_frame *)frm;
/* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */
/* FC type/subtype */
aad[0] = wh->i_fc[0];
/* Mask FC Retry, PwrMgt, MoreData flags to zero */
aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
IEEE80211_FC1_MORE_DATA);
/* A1 || A2 || A3 */
qdf_mem_copy(aad + 2, wh->i_addr_all, 3 * QDF_MAC_ADDR_SIZE);
/* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
nBytes = AAD_LEN + (efrm - (uint8_t *) (wh + 1));
input = (uint8_t *) qdf_mem_malloc(nBytes);
if (!input) {
cds_err("Memory allocation failed");
ret = QDF_STATUS_E_NOMEM;
goto err_tfm;
}
/* Copy the AAD, MMIE with 8 bit MIC zeroed out */
qdf_mem_copy(input, aad, AAD_LEN);
qdf_mem_copy(input + AAD_LEN, (uint8_t *) (wh + 1),
nBytes - AAD_LEN - CMAC_TLEN);
cds_cmac_calc_mic(tfm, input, nBytes, mic);
qdf_mem_free(input);
cds_err("CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
mic[0], mic[1], mic[2], mic[3],
mic[4], mic[5], mic[6], mic[7]);
if (qdf_mem_cmp(mic, mmie->mic, CMAC_TLEN) != 0) {
/* MMIE MIC mismatch */
cds_err("BC/MC MGMT frame MMIE MIC check Failed"
" rmic %02X %02X %02X %02X %02X %02X %02X %02X"
" cmic %02X %02X %02X %02X %02X %02X %02X %02X",
mmie->mic[0], mmie->mic[1], mmie->mic[2],
mmie->mic[3], mmie->mic[4], mmie->mic[5],
mmie->mic[6], mmie->mic[7], mic[0], mic[1], mic[2],
mic[3], mic[4], mic[5], mic[6], mic[7]);
return false;
}
/* Update IPN */
qdf_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN);
err_tfm:
if (tfm)
cds_crypto_free_cipher(tfm);
return !ret ? true : false;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
uint8_t cds_get_gmac_mmie_size(void)
{
@ -472,119 +88,6 @@ uint8_t cds_get_gmac_mmie_size(void)
}
#endif
/**
* ipn_swap: Swaps ipn
* @d: destination pointer
* @s: source pointer
*
* Return: None
*/
static inline void ipn_swap(u8 *d, const u8 *s)
{
*d++ = s[5];
*d++ = s[4];
*d++ = s[3];
*d++ = s[2];
*d++ = s[1];
*d = s[0];
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
bool cds_is_gmac_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm,
uint8_t *efrm, uint16_t key_length)
{
struct ieee80211_mmie_16 *mmie;
struct ieee80211_frame *wh;
uint8_t rx_ipn[6], aad[AAD_LEN];
uint8_t mic[IEEE80211_MMIE_GMAC_MICLEN] = {0};
uint16_t data_len;
uint8_t gmac_nonce[GMAC_NONCE_LEN];
uint8_t iv[AES_BLOCK_SIZE] = {0};
int ret;
/* Check if frame is invalid length */
if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) {
cds_err("Invalid frame length");
return false;
}
mmie = (struct ieee80211_mmie_16 *)(efrm - sizeof(*mmie));
/* Check Element ID */
if ((mmie->element_id != WLAN_ELEMID_MMIE) ||
(mmie->length != (sizeof(*mmie) - 2))) {
cds_err("IE is not Mgmt MIC IE or Invalid length");
/* IE is not Mgmt MIC IE or invalid length */
return false;
}
/* Validate IPN */
ipn_swap(rx_ipn, mmie->sequence_number);
if (qdf_mem_cmp(rx_ipn, ipn, IEEE80211_MMIE_IPNLEN) <= 0) {
/* Replay error */
cds_debug("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]);
return false;
}
/* Construct AAD */
wh = (struct ieee80211_frame *)frm;
/* Generate AAD: FC(masked) || A1 || A2 || A3 */
/* FC type/subtype */
aad[0] = wh->i_fc[0];
/* Mask FC Retry, PwrMgt, MoreData flags to zero */
aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
IEEE80211_FC1_MORE_DATA);
/* A1 || A2 || A3 */
qdf_mem_copy(aad + 2, wh->i_addr_all, 3 * QDF_MAC_ADDR_SIZE);
data_len = efrm - (uint8_t *) (wh + 1) - IEEE80211_MMIE_GMAC_MICLEN;
/* IV */
qdf_mem_copy(gmac_nonce, wh->i_addr2, QDF_MAC_ADDR_SIZE);
qdf_mem_copy(gmac_nonce + QDF_MAC_ADDR_SIZE, rx_ipn,
IEEE80211_MMIE_IPNLEN);
qdf_mem_copy(iv, gmac_nonce, GMAC_NONCE_LEN);
iv[AES_BLOCK_SIZE - 1] = 0x01;
ret = qdf_crypto_aes_gmac(igtk, key_length, iv, aad,
(uint8_t *) (wh + 1), data_len, mic);
if (ret) {
cds_err("qdf_crypto_aes_gmac failed %d", ret);
return false;
}
if (qdf_mem_cmp(mic, mmie->mic, IEEE80211_MMIE_GMAC_MICLEN) != 0) {
/* MMIE MIC mismatch */
cds_debug("BC/MC MGMT frame MMIE MIC check Failed"
" rmic %02X %02X %02X %02X %02X %02X %02X %02X"
" %02X %02X %02X %02X %02X %02X %02X %02X",
mmie->mic[0], mmie->mic[1], mmie->mic[2],
mmie->mic[3], mmie->mic[4], mmie->mic[5],
mmie->mic[6], mmie->mic[7], mmie->mic[8],
mmie->mic[9], mmie->mic[10], mmie->mic[11],
mmie->mic[12], mmie->mic[13], mmie->mic[14],
mmie->mic[15]);
return false;
}
/* Update IPN */
qdf_mem_copy(ipn, rx_ipn, IEEE80211_MMIE_IPNLEN);
return true;
}
#else
bool cds_is_gmac_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm,
uint8_t *efrm, uint16_t key_length)
{
return false;
}
#endif
#endif /* WLAN_FEATURE_11W */
uint32_t cds_chan_to_freq(uint8_t chan)

View File

@ -632,30 +632,6 @@ struct wma_version_info {
u_int32_t revision;
};
#define CMAC_IPN_LEN (6)
#define WMA_IGTK_KEY_INDEX_4 (4)
#define WMA_IGTK_KEY_INDEX_5 (5)
/**
* struct wma_igtk_ipn_t - GTK IPN info
* @ipn: IPN info
*/
typedef struct {
uint8_t ipn[CMAC_IPN_LEN];
} wma_igtk_ipn_t;
/**
* struct wma_igtk_key_t - GTK key
* @key_id: key id
*/
typedef struct {
/* 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;
struct roam_synch_frame_ind {
uint32_t bcn_probe_rsp_len;
uint8_t *bcn_probe_rsp;
@ -699,7 +675,6 @@ struct wma_invalid_peer_params {
* @addBssStaContext: add bss context
* @aid: association id
* @rmfEnabled: Robust Management Frame (RMF) enabled/disabled
* @key: GTK key
* @uapsd_cached_val: uapsd cached value
* @stats_rsp: stats response
* @del_staself_req: delete sta self request
@ -750,7 +725,6 @@ struct wma_txrx_node {
tAddStaParams *addBssStaContext;
uint8_t aid;
uint8_t rmfEnabled;
wma_igtk_key_t key;
uint32_t uapsd_cached_val;
void *del_staself_req;
bool is_del_sta_defered;
@ -2452,17 +2426,6 @@ void wma_update_set_key(uint8_t session_id, bool pairwise,
uint8_t key_index,
enum wlan_crypto_cipher_type cipher_type);
/**
* wma_get_igtk() - Get the IGTK that was stored in the session earlier
* @iface: Interface for which the key is being requested
* @key_len: key length
* @igtk_key_idx: igtk key idx
*
* Return: Pointer to the key
*/
uint8_t *wma_get_igtk(struct wma_txrx_node *iface, uint16_t *key_len,
uint16_t igtk_key_idx);
#ifdef WLAN_FEATURE_MOTION_DETECTION
/**
* wma_motion_det_host_event_handler - motion detection event handler

View File

@ -2351,30 +2351,6 @@ static void wma_update_tx_send_params(struct tx_send_params *tx_param,
tx_param->preamble_type);
}
#ifdef WLAN_FEATURE_11W
uint8_t *wma_get_igtk(struct wma_txrx_node *iface, uint16_t *key_len,
uint16_t igtk_key_idx)
{
struct wlan_crypto_key *crypto_key;
if (!(igtk_key_idx == WMA_IGTK_KEY_INDEX_4 ||
igtk_key_idx == WMA_IGTK_KEY_INDEX_5)) {
wma_err("Invalid igtk_key_idx %d", igtk_key_idx);
*key_len = 0;
return NULL;
}
crypto_key = wlan_crypto_get_key(iface->vdev, igtk_key_idx);
if (!crypto_key) {
wma_err("IGTK not found for igtk_idx %d", igtk_key_idx);
*key_len = 0;
return NULL;
}
*key_len = crypto_key->keylen;
return &crypto_key->keyval[0];
}
#endif
QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
eFrameType frmType, eFrameTxDir txDir, uint8_t tid,
wma_tx_dwnld_comp_callback tx_frm_download_comp_cb,
@ -2397,8 +2373,6 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
uint8_t *pFrame = NULL;
void *pPacket = NULL;
uint16_t newFrmLen = 0;
uint8_t *igtk;
uint16_t key_len;
#endif /* WLAN_FEATURE_11W */
struct wma_txrx_node *iface;
struct mac_context *mac;
@ -2520,10 +2494,24 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
(qdf_nbuf_data(tx_frame));
}
} else {
int8_t igtk_key_id;
uint16_t mmie_size;
int32_t mgmtcipherset;
mgmtcipherset = wlan_crypto_get_param(iface->vdev,
WLAN_CRYPTO_PARAM_MGMT_CIPHER);
if (mgmtcipherset <= 0) {
wma_err("Invalid key cipher %d", mgmtcipherset);
cds_packet_free((void *)tx_frame);
return -EINVAL;
}
if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_CMAC))
mmie_size = cds_get_mmie_size();
else
mmie_size = cds_get_gmac_mmie_size();
/* Allocate extra bytes for MMIE */
newFrmLen = frmLen + IEEE80211_MMIE_LEN;
newFrmLen = frmLen + mmie_size;
qdf_status = cds_packet_alloc((uint16_t) newFrmLen,
(void **)&pFrame,
(void **)&pPacket);
@ -2539,31 +2527,16 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
/*
* Initialize the frame with 0's and only fill
* MAC header and data. MMIE field will be
* filled by cds_attach_mmie API
* filled by wlan_crypto_add_mmie API
*/
qdf_mem_zero(pFrame, newFrmLen);
qdf_mem_copy(pFrame, wh, sizeof(*wh));
qdf_mem_copy(pFrame + sizeof(*wh),
pData + sizeof(*wh), frmLen - sizeof(*wh));
igtk_key_id =
wlan_crypto_get_default_key_idx(iface->vdev,
true);
/* Get actual igtk key id adding 4 */
igtk_key_id += WMA_IGTK_KEY_INDEX_4;
igtk = wma_get_igtk(iface, &key_len, igtk_key_id);
if (!igtk) {
wma_err_rl("IGTK not present for igtk_key_id %d",
igtk_key_id);
cds_packet_free((void *)tx_frame);
cds_packet_free((void *)pPacket);
goto error;
}
if (!cds_attach_mmie(igtk, iface->key.key_id[
igtk_key_id -
WMA_IGTK_KEY_INDEX_4].ipn,
igtk_key_id,
pFrame,
pFrame + newFrmLen, newFrmLen)) {
/* The API expect length without the mmie size */
if (!wlan_crypto_add_mmie(iface->vdev, pFrame,
frmLen)) {
wma_alert("Failed to attach MMIE");
/* Free the original packet memory */
cds_packet_free((void *)tx_frame);

View File

@ -2235,17 +2235,6 @@ static void wma_send_vdev_down_req(tp_wma_handle wma,
sizeof(*resp), resp);
}
#ifdef WLAN_FEATURE_11W
static void wma_clear_iface_key(struct wma_txrx_node *iface)
{
qdf_mem_zero(&iface->key, sizeof(iface->key));
}
#else
static void wma_clear_iface_key(struct wma_txrx_node *iface)
{
}
#endif
QDF_STATUS
__wma_handle_vdev_stop_rsp(struct vdev_stop_response *resp_event)
{
@ -2288,8 +2277,6 @@ __wma_handle_vdev_stop_rsp(struct vdev_stop_response *resp_event)
return QDF_STATUS_E_INVAL;
}
/* Clear key information */
wma_clear_iface_key(iface);
status = mlme_get_vdev_stop_type(iface->vdev, &vdev_stop_type);
if (QDF_IS_STATUS_ERROR(status)) {
WMA_LOGE("%s: Failed to get wma req msg type for vdev id %d",

View File

@ -5390,15 +5390,6 @@ void wma_set_peer_ucast_cipher(uint8_t *mac_addr,
1 << cipher_cap, mac_addr);
}
static void wma_reset_ipn(struct wma_txrx_node *iface, uint8_t key_index)
{
if (key_index == WMA_IGTK_KEY_INDEX_4 ||
key_index == WMA_IGTK_KEY_INDEX_5)
qdf_mem_zero(iface->key.key_id[key_index -
WMA_IGTK_KEY_INDEX_4].ipn,
CMAC_IPN_LEN);
}
void wma_update_set_key(uint8_t session_id, bool pairwise,
uint8_t key_index,
enum wlan_crypto_cipher_type cipher_type)
@ -5416,10 +5407,9 @@ void wma_update_set_key(uint8_t session_id, bool pairwise,
return;
}
if (iface) {
wma_reset_ipn(iface, key_index);
if (iface)
iface->is_waiting_for_key = false;
}
if (!pairwise && iface) {
/* Its GTK release the wake lock */
wma_debug("Release set key wake lock");

View File

@ -3092,19 +3092,12 @@ wma_is_ccmp_pn_replay_attack(tp_wma_handle wma, struct ieee80211_frame *wh,
*
* Return: 0 for success or error code
*/
static
int wma_process_bip(tp_wma_handle wma_handle,
struct wma_txrx_node *iface,
struct ieee80211_frame *wh,
qdf_nbuf_t wbuf
)
int wma_process_bip(tp_wma_handle wma_handle, struct wma_txrx_node *iface,
struct ieee80211_frame *wh, qdf_nbuf_t wbuf)
{
uint16_t mmie_size;
uint16_t key_id;
uint8_t *efrm;
uint8_t *igtk;
uint16_t key_len;
int32_t mgmtcipherset;
enum wlan_crypto_cipher_type key_cipher;
@ -3112,7 +3105,7 @@ int wma_process_bip(tp_wma_handle wma_handle,
mgmtcipherset = wlan_crypto_get_param(iface->vdev,
WLAN_CRYPTO_PARAM_MGMT_CIPHER);
if (!mgmtcipherset || mgmtcipherset < 0) {
if (mgmtcipherset <= 0) {
wma_err("Invalid key cipher %d", mgmtcipherset);
return -EINVAL;
}
@ -3133,28 +3126,16 @@ int wma_process_bip(tp_wma_handle wma_handle,
/* Check if frame is invalid length */
if (efrm - (uint8_t *)wh < sizeof(*wh) + mmie_size) {
WMA_LOGE(FL("Invalid frame length"));
wma_err("Invalid frame length");
return -EINVAL;
}
key_id = (uint16_t)*(efrm - mmie_size + 2);
if (!((key_id == WMA_IGTK_KEY_INDEX_4)
|| (key_id == WMA_IGTK_KEY_INDEX_5))) {
WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
return -EINVAL;
}
wma_debug("key_cipher %d key_id %d", key_cipher, key_id);
igtk = wma_get_igtk(iface, &key_len, key_id);
switch (key_cipher) {
case WLAN_CRYPTO_CIPHER_AES_CMAC:
if (!wmi_service_enabled(wma_handle->wmi_handle,
wmi_service_sta_pmf_offload)) {
if (!cds_is_mmie_valid(igtk, iface->key.key_id[
key_id -
WMA_IGTK_KEY_INDEX_4].ipn,
(uint8_t *)wh, efrm)) {
if (!wlan_crypto_is_mmie_valid(iface->vdev,
(uint8_t *)wh, efrm)) {
wma_debug("BC/MC MIC error or MMIE not present, dropping the frame");
return -EINVAL;
}
@ -3164,11 +3145,8 @@ int wma_process_bip(tp_wma_handle wma_handle,
case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
if (!wmi_service_enabled(wma_handle->wmi_handle,
wmi_service_gmac_offload_support)) {
if (!cds_is_gmac_mmie_valid(igtk,
iface->key.key_id[key_id -
WMA_IGTK_KEY_INDEX_4].ipn,
(uint8_t *)wh, efrm,
key_len)) {
if (!wlan_crypto_is_mmie_valid(iface->vdev,
(uint8_t *)wh, efrm)) {
wma_debug("BC/MC GMAC MIC error or MMIE not present, dropping the frame");
return -EINVAL;
}