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:

committed by
nshrivas

orang tua
405d82a9cb
melakukan
3f29b6c7f2
@@ -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 */
|
|
@@ -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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* 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);
|
enum cds_band_type cds_chan_to_band(uint32_t chan);
|
||||||
|
|
||||||
#ifdef WLAN_FEATURE_11W
|
#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);
|
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
|
* cds_get_gmac_mmie_size: Gives length of GMAC MMIE size
|
||||||
|
@@ -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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -40,8 +40,6 @@
|
|||||||
#include "qdf_trace.h"
|
#include "qdf_trace.h"
|
||||||
#include "cds_utils.h"
|
#include "cds_utils.h"
|
||||||
#include "qdf_mem.h"
|
#include "qdf_mem.h"
|
||||||
#include "cds_crypto.h"
|
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
@@ -57,10 +55,6 @@
|
|||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Preprocessor Definitions and Constants
|
* 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
|
* Type Declarations
|
||||||
@@ -75,111 +69,6 @@
|
|||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
Function Definitions and Documentation
|
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
|
#ifdef WLAN_FEATURE_11W
|
||||||
uint8_t cds_get_mmie_size(void)
|
uint8_t cds_get_mmie_size(void)
|
||||||
@@ -187,279 +76,6 @@ uint8_t cds_get_mmie_size(void)
|
|||||||
return sizeof(struct ieee80211_mmie);
|
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))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
|
||||||
uint8_t cds_get_gmac_mmie_size(void)
|
uint8_t cds_get_gmac_mmie_size(void)
|
||||||
{
|
{
|
||||||
@@ -472,119 +88,6 @@ uint8_t cds_get_gmac_mmie_size(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 */
|
#endif /* WLAN_FEATURE_11W */
|
||||||
|
|
||||||
uint32_t cds_chan_to_freq(uint8_t chan)
|
uint32_t cds_chan_to_freq(uint8_t chan)
|
||||||
|
@@ -632,30 +632,6 @@ struct wma_version_info {
|
|||||||
u_int32_t revision;
|
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 {
|
struct roam_synch_frame_ind {
|
||||||
uint32_t bcn_probe_rsp_len;
|
uint32_t bcn_probe_rsp_len;
|
||||||
uint8_t *bcn_probe_rsp;
|
uint8_t *bcn_probe_rsp;
|
||||||
@@ -699,7 +675,6 @@ struct wma_invalid_peer_params {
|
|||||||
* @addBssStaContext: add bss context
|
* @addBssStaContext: add bss context
|
||||||
* @aid: association id
|
* @aid: association id
|
||||||
* @rmfEnabled: Robust Management Frame (RMF) enabled/disabled
|
* @rmfEnabled: Robust Management Frame (RMF) enabled/disabled
|
||||||
* @key: GTK key
|
|
||||||
* @uapsd_cached_val: uapsd cached value
|
* @uapsd_cached_val: uapsd cached value
|
||||||
* @stats_rsp: stats response
|
* @stats_rsp: stats response
|
||||||
* @del_staself_req: delete sta self request
|
* @del_staself_req: delete sta self request
|
||||||
@@ -750,7 +725,6 @@ struct wma_txrx_node {
|
|||||||
tAddStaParams *addBssStaContext;
|
tAddStaParams *addBssStaContext;
|
||||||
uint8_t aid;
|
uint8_t aid;
|
||||||
uint8_t rmfEnabled;
|
uint8_t rmfEnabled;
|
||||||
wma_igtk_key_t key;
|
|
||||||
uint32_t uapsd_cached_val;
|
uint32_t uapsd_cached_val;
|
||||||
void *del_staself_req;
|
void *del_staself_req;
|
||||||
bool is_del_sta_defered;
|
bool is_del_sta_defered;
|
||||||
@@ -2452,17 +2426,6 @@ void wma_update_set_key(uint8_t session_id, bool pairwise,
|
|||||||
uint8_t key_index,
|
uint8_t key_index,
|
||||||
enum wlan_crypto_cipher_type cipher_type);
|
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
|
#ifdef WLAN_FEATURE_MOTION_DETECTION
|
||||||
/**
|
/**
|
||||||
* wma_motion_det_host_event_handler - motion detection event handler
|
* wma_motion_det_host_event_handler - motion detection event handler
|
||||||
|
@@ -2351,30 +2351,6 @@ static void wma_update_tx_send_params(struct tx_send_params *tx_param,
|
|||||||
tx_param->preamble_type);
|
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,
|
QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
|
||||||
eFrameType frmType, eFrameTxDir txDir, uint8_t tid,
|
eFrameType frmType, eFrameTxDir txDir, uint8_t tid,
|
||||||
wma_tx_dwnld_comp_callback tx_frm_download_comp_cb,
|
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;
|
uint8_t *pFrame = NULL;
|
||||||
void *pPacket = NULL;
|
void *pPacket = NULL;
|
||||||
uint16_t newFrmLen = 0;
|
uint16_t newFrmLen = 0;
|
||||||
uint8_t *igtk;
|
|
||||||
uint16_t key_len;
|
|
||||||
#endif /* WLAN_FEATURE_11W */
|
#endif /* WLAN_FEATURE_11W */
|
||||||
struct wma_txrx_node *iface;
|
struct wma_txrx_node *iface;
|
||||||
struct mac_context *mac;
|
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));
|
(qdf_nbuf_data(tx_frame));
|
||||||
}
|
}
|
||||||
} else {
|
} 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 */
|
/* Allocate extra bytes for MMIE */
|
||||||
newFrmLen = frmLen + IEEE80211_MMIE_LEN;
|
newFrmLen = frmLen + mmie_size;
|
||||||
qdf_status = cds_packet_alloc((uint16_t) newFrmLen,
|
qdf_status = cds_packet_alloc((uint16_t) newFrmLen,
|
||||||
(void **)&pFrame,
|
(void **)&pFrame,
|
||||||
(void **)&pPacket);
|
(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
|
* Initialize the frame with 0's and only fill
|
||||||
* MAC header and data. MMIE field will be
|
* 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_zero(pFrame, newFrmLen);
|
||||||
qdf_mem_copy(pFrame, wh, sizeof(*wh));
|
qdf_mem_copy(pFrame, wh, sizeof(*wh));
|
||||||
qdf_mem_copy(pFrame + sizeof(*wh),
|
qdf_mem_copy(pFrame + sizeof(*wh),
|
||||||
pData + sizeof(*wh), frmLen - sizeof(*wh));
|
pData + sizeof(*wh), frmLen - sizeof(*wh));
|
||||||
igtk_key_id =
|
|
||||||
wlan_crypto_get_default_key_idx(iface->vdev,
|
/* The API expect length without the mmie size */
|
||||||
true);
|
if (!wlan_crypto_add_mmie(iface->vdev, pFrame,
|
||||||
/* Get actual igtk key id adding 4 */
|
frmLen)) {
|
||||||
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)) {
|
|
||||||
wma_alert("Failed to attach MMIE");
|
wma_alert("Failed to attach MMIE");
|
||||||
/* Free the original packet memory */
|
/* Free the original packet memory */
|
||||||
cds_packet_free((void *)tx_frame);
|
cds_packet_free((void *)tx_frame);
|
||||||
|
@@ -2235,17 +2235,6 @@ static void wma_send_vdev_down_req(tp_wma_handle wma,
|
|||||||
sizeof(*resp), resp);
|
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
|
QDF_STATUS
|
||||||
__wma_handle_vdev_stop_rsp(struct vdev_stop_response *resp_event)
|
__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;
|
return QDF_STATUS_E_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear key information */
|
|
||||||
wma_clear_iface_key(iface);
|
|
||||||
status = mlme_get_vdev_stop_type(iface->vdev, &vdev_stop_type);
|
status = mlme_get_vdev_stop_type(iface->vdev, &vdev_stop_type);
|
||||||
if (QDF_IS_STATUS_ERROR(status)) {
|
if (QDF_IS_STATUS_ERROR(status)) {
|
||||||
WMA_LOGE("%s: Failed to get wma req msg type for vdev id %d",
|
WMA_LOGE("%s: Failed to get wma req msg type for vdev id %d",
|
||||||
|
@@ -5390,15 +5390,6 @@ void wma_set_peer_ucast_cipher(uint8_t *mac_addr,
|
|||||||
1 << cipher_cap, 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,
|
void wma_update_set_key(uint8_t session_id, bool pairwise,
|
||||||
uint8_t key_index,
|
uint8_t key_index,
|
||||||
enum wlan_crypto_cipher_type cipher_type)
|
enum wlan_crypto_cipher_type cipher_type)
|
||||||
@@ -5416,10 +5407,9 @@ void wma_update_set_key(uint8_t session_id, bool pairwise,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iface) {
|
if (iface)
|
||||||
wma_reset_ipn(iface, key_index);
|
|
||||||
iface->is_waiting_for_key = false;
|
iface->is_waiting_for_key = false;
|
||||||
}
|
|
||||||
if (!pairwise && iface) {
|
if (!pairwise && iface) {
|
||||||
/* Its GTK release the wake lock */
|
/* Its GTK release the wake lock */
|
||||||
wma_debug("Release set key wake lock");
|
wma_debug("Release set key wake lock");
|
||||||
|
@@ -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
|
* Return: 0 for success or error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static
|
static
|
||||||
int wma_process_bip(tp_wma_handle wma_handle,
|
int wma_process_bip(tp_wma_handle wma_handle, struct wma_txrx_node *iface,
|
||||||
struct wma_txrx_node *iface,
|
struct ieee80211_frame *wh, qdf_nbuf_t wbuf)
|
||||||
struct ieee80211_frame *wh,
|
|
||||||
qdf_nbuf_t wbuf
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
uint16_t mmie_size;
|
uint16_t mmie_size;
|
||||||
uint16_t key_id;
|
|
||||||
uint8_t *efrm;
|
uint8_t *efrm;
|
||||||
uint8_t *igtk;
|
|
||||||
uint16_t key_len;
|
|
||||||
int32_t mgmtcipherset;
|
int32_t mgmtcipherset;
|
||||||
enum wlan_crypto_cipher_type key_cipher;
|
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,
|
mgmtcipherset = wlan_crypto_get_param(iface->vdev,
|
||||||
WLAN_CRYPTO_PARAM_MGMT_CIPHER);
|
WLAN_CRYPTO_PARAM_MGMT_CIPHER);
|
||||||
if (!mgmtcipherset || mgmtcipherset < 0) {
|
if (mgmtcipherset <= 0) {
|
||||||
wma_err("Invalid key cipher %d", mgmtcipherset);
|
wma_err("Invalid key cipher %d", mgmtcipherset);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -3133,28 +3126,16 @@ int wma_process_bip(tp_wma_handle wma_handle,
|
|||||||
|
|
||||||
/* Check if frame is invalid length */
|
/* Check if frame is invalid length */
|
||||||
if (efrm - (uint8_t *)wh < sizeof(*wh) + mmie_size) {
|
if (efrm - (uint8_t *)wh < sizeof(*wh) + mmie_size) {
|
||||||
WMA_LOGE(FL("Invalid frame length"));
|
wma_err("Invalid frame length");
|
||||||
return -EINVAL;
|
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) {
|
switch (key_cipher) {
|
||||||
case WLAN_CRYPTO_CIPHER_AES_CMAC:
|
case WLAN_CRYPTO_CIPHER_AES_CMAC:
|
||||||
if (!wmi_service_enabled(wma_handle->wmi_handle,
|
if (!wmi_service_enabled(wma_handle->wmi_handle,
|
||||||
wmi_service_sta_pmf_offload)) {
|
wmi_service_sta_pmf_offload)) {
|
||||||
if (!cds_is_mmie_valid(igtk, iface->key.key_id[
|
if (!wlan_crypto_is_mmie_valid(iface->vdev,
|
||||||
key_id -
|
(uint8_t *)wh, efrm)) {
|
||||||
WMA_IGTK_KEY_INDEX_4].ipn,
|
|
||||||
(uint8_t *)wh, efrm)) {
|
|
||||||
wma_debug("BC/MC MIC error or MMIE not present, dropping the frame");
|
wma_debug("BC/MC MIC error or MMIE not present, dropping the frame");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -3164,11 +3145,8 @@ int wma_process_bip(tp_wma_handle wma_handle,
|
|||||||
case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
|
case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
|
||||||
if (!wmi_service_enabled(wma_handle->wmi_handle,
|
if (!wmi_service_enabled(wma_handle->wmi_handle,
|
||||||
wmi_service_gmac_offload_support)) {
|
wmi_service_gmac_offload_support)) {
|
||||||
if (!cds_is_gmac_mmie_valid(igtk,
|
if (!wlan_crypto_is_mmie_valid(iface->vdev,
|
||||||
iface->key.key_id[key_id -
|
(uint8_t *)wh, efrm)) {
|
||||||
WMA_IGTK_KEY_INDEX_4].ipn,
|
|
||||||
(uint8_t *)wh, efrm,
|
|
||||||
key_len)) {
|
|
||||||
wma_debug("BC/MC GMAC MIC error or MMIE not present, dropping the frame");
|
wma_debug("BC/MC GMAC MIC error or MMIE not present, dropping the frame");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user