![Joe Perches](/assets/img/avatar_default.png)
Preliminary to removing compare_ether_addr altogether: Use the new bool function ether_addr_equal to add some clarity and reduce the likelihood for misuse of compare_ether_addr for sorting. Additionally: Used is_zero_ether_addr, removed now unused variable Converted uses of &foo[0] to foo Done via cocci script: (and a little typing) $ cat compare_ether_addr.cocci @@ expression a,b; @@ - !compare_ether_addr(a, b) + ether_addr_equal(a, b) @@ expression a,b; @@ - compare_ether_addr(a, b) + !ether_addr_equal(a, b) @@ expression a,b; @@ - !ether_addr_equal(a, b) == 0 + ether_addr_equal(a, b) @@ expression a,b; @@ - !ether_addr_equal(a, b) != 0 + !ether_addr_equal(a, b) @@ expression a,b; @@ - ether_addr_equal(a, b) == 0 + !ether_addr_equal(a, b) @@ expression a,b; @@ - ether_addr_equal(a, b) != 0 + ether_addr_equal(a, b) @@ expression a,b; @@ - !!ether_addr_equal(a, b) + ether_addr_equal(a, b) Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
799 lines
24 KiB
C
799 lines
24 KiB
C
/*
|
|
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
*
|
|
* File: key.c
|
|
*
|
|
* Purpose: Implement functions for 802.11i Key management
|
|
*
|
|
* Author: Jerry Chen
|
|
*
|
|
* Date: May 29, 2003
|
|
*
|
|
* Functions:
|
|
* KeyvInitTable - Init Key management table
|
|
* KeybGetKey - Get Key from table
|
|
* KeybSetKey - Set Key to table
|
|
* KeybRemoveKey - Remove Key from table
|
|
* KeybGetTransmitKey - Get Transmit Key from table
|
|
*
|
|
* Revision History:
|
|
*
|
|
*/
|
|
|
|
#include "tmacro.h"
|
|
#include "key.h"
|
|
#include "mac.h"
|
|
|
|
/*--------------------- Static Definitions -------------------------*/
|
|
|
|
/*--------------------- Static Classes ----------------------------*/
|
|
|
|
/*--------------------- Static Variables --------------------------*/
|
|
static int msglevel = MSG_LEVEL_INFO;
|
|
//static int msglevel =MSG_LEVEL_DEBUG;
|
|
/*--------------------- Static Functions --------------------------*/
|
|
|
|
/*--------------------- Export Variables --------------------------*/
|
|
|
|
/*--------------------- Static Definitions -------------------------*/
|
|
|
|
/*--------------------- Static Classes ----------------------------*/
|
|
|
|
/*--------------------- Static Variables --------------------------*/
|
|
|
|
/*--------------------- Static Functions --------------------------*/
|
|
static void
|
|
s_vCheckKeyTableValid(PSKeyManagement pTable, unsigned long dwIoBase)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
(pTable->KeyTable[i].PairwiseKey.bKeyValid == false) &&
|
|
(pTable->KeyTable[i].GroupKey[0].bKeyValid == false) &&
|
|
(pTable->KeyTable[i].GroupKey[1].bKeyValid == false) &&
|
|
(pTable->KeyTable[i].GroupKey[2].bKeyValid == false) &&
|
|
(pTable->KeyTable[i].GroupKey[3].bKeyValid == false)
|
|
) {
|
|
pTable->KeyTable[i].bInUse = false;
|
|
pTable->KeyTable[i].wKeyCtl = 0;
|
|
pTable->KeyTable[i].bSoftWEP = false;
|
|
MACvDisableKeyEntry(dwIoBase, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------- Export Functions --------------------------*/
|
|
|
|
/*
|
|
* Description: Init Key management table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: none
|
|
*
|
|
*/
|
|
void KeyvInitTable(PSKeyManagement pTable, unsigned long dwIoBase)
|
|
{
|
|
int i;
|
|
int jj;
|
|
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
pTable->KeyTable[i].bInUse = false;
|
|
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
|
|
pTable->KeyTable[i].PairwiseKey.pvKeyTable = (void *)&pTable->KeyTable[i];
|
|
for (jj = 0; jj < MAX_GROUP_KEY; jj++) {
|
|
pTable->KeyTable[i].GroupKey[jj].bKeyValid = false;
|
|
pTable->KeyTable[i].GroupKey[jj].pvKeyTable = (void *)&pTable->KeyTable[i];
|
|
}
|
|
pTable->KeyTable[i].wKeyCtl = 0;
|
|
pTable->KeyTable[i].dwGTKeyIndex = 0;
|
|
pTable->KeyTable[i].bSoftWEP = false;
|
|
MACvDisableKeyEntry(dwIoBase, i);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Description: Get Key from table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* pbyBSSID - BSSID of Key
|
|
* dwKeyIndex - Key Index (0xFFFFFFFF means pairwise key)
|
|
* Out:
|
|
* pKey - Key return
|
|
*
|
|
* Return Value: true if found otherwise false
|
|
*
|
|
*/
|
|
bool KeybGetKey(
|
|
PSKeyManagement pTable,
|
|
unsigned char *pbyBSSID,
|
|
unsigned long dwKeyIndex,
|
|
PSKeyItem *pKey
|
|
)
|
|
{
|
|
int i;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetKey() \n");
|
|
|
|
*pKey = NULL;
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
|
|
if (dwKeyIndex == 0xFFFFFFFF) {
|
|
if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
|
|
*pKey = &(pTable->KeyTable[i].PairwiseKey);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else if (dwKeyIndex < MAX_GROUP_KEY) {
|
|
if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == true) {
|
|
*pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Description: Set Key to table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* pbyBSSID - BSSID of Key
|
|
* dwKeyIndex - Key index (reference to NDIS DDK)
|
|
* uKeyLength - Key length
|
|
* KeyRSC - Key RSC
|
|
* pbyKey - Pointer to key
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if success otherwise false
|
|
*
|
|
*/
|
|
bool KeybSetKey(
|
|
PSKeyManagement pTable,
|
|
unsigned char *pbyBSSID,
|
|
unsigned long dwKeyIndex,
|
|
unsigned long uKeyLength,
|
|
PQWORD pKeyRSC,
|
|
unsigned char *pbyKey,
|
|
unsigned char byKeyDecMode,
|
|
unsigned long dwIoBase,
|
|
unsigned char byLocalID
|
|
)
|
|
{
|
|
int i, j;
|
|
unsigned int ii;
|
|
PSKeyItem pKey;
|
|
unsigned int uKeyIdx;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetKey: %lX\n", dwKeyIndex);
|
|
|
|
j = (MAX_KEY_TABLE-1);
|
|
for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
|
|
if ((pTable->KeyTable[i].bInUse == false) &&
|
|
(j == (MAX_KEY_TABLE-1))) {
|
|
// found empty table
|
|
j = i;
|
|
}
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
|
|
// found table already exist
|
|
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
|
|
// Pairwise key
|
|
pKey = &(pTable->KeyTable[i].PairwiseKey);
|
|
pTable->KeyTable[i].wKeyCtl &= 0xFFF0; // clear pairwise key control filed
|
|
pTable->KeyTable[i].wKeyCtl |= byKeyDecMode;
|
|
uKeyIdx = 4; // use HW key entry 4 for pairwise key
|
|
} else {
|
|
// Group key
|
|
if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
|
|
return false;
|
|
pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
|
|
if ((dwKeyIndex & TRANSMIT_KEY) != 0) {
|
|
// Group transmit key
|
|
pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
|
|
}
|
|
pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed
|
|
pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
|
|
pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address
|
|
uKeyIdx = (dwKeyIndex & 0x000000FF);
|
|
}
|
|
pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly
|
|
|
|
pKey->bKeyValid = true;
|
|
pKey->uKeyLength = uKeyLength;
|
|
pKey->dwKeyIndex = dwKeyIndex;
|
|
pKey->byCipherSuite = byKeyDecMode;
|
|
memcpy(pKey->abyKey, pbyKey, uKeyLength);
|
|
if (byKeyDecMode == KEY_CTL_WEP) {
|
|
if (uKeyLength == WLAN_WEP40_KEYLEN)
|
|
pKey->abyKey[15] &= 0x7F;
|
|
if (uKeyLength == WLAN_WEP104_KEYLEN)
|
|
pKey->abyKey[15] |= 0x80;
|
|
}
|
|
MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
|
|
|
|
if ((dwKeyIndex & USE_KEYRSC) == 0) {
|
|
// RSC set by NIC
|
|
memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
|
|
} else {
|
|
memcpy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD));
|
|
}
|
|
pKey->dwTSC47_16 = 0;
|
|
pKey->wTSC15_0 = 0;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R): \n");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
|
|
//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", pKey->uKeyLength);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
|
|
for (ii = 0; ii < pKey->uKeyLength; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
if (j < (MAX_KEY_TABLE-1)) {
|
|
memcpy(pTable->KeyTable[j].abyBSSID, pbyBSSID, ETH_ALEN);
|
|
pTable->KeyTable[j].bInUse = true;
|
|
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
|
|
// Pairwise key
|
|
pKey = &(pTable->KeyTable[j].PairwiseKey);
|
|
pTable->KeyTable[j].wKeyCtl &= 0xFFF0; // clear pairwise key control filed
|
|
pTable->KeyTable[j].wKeyCtl |= byKeyDecMode;
|
|
uKeyIdx = 4; // use HW key entry 4 for pairwise key
|
|
} else {
|
|
// Group key
|
|
if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
|
|
return false;
|
|
pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]);
|
|
if ((dwKeyIndex & TRANSMIT_KEY) != 0) {
|
|
// Group transmit key
|
|
pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex;
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j);
|
|
}
|
|
pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed
|
|
pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4);
|
|
pTable->KeyTable[j].wKeyCtl |= 0x0040; // use group key for group address
|
|
uKeyIdx = (dwKeyIndex & 0x000000FF);
|
|
}
|
|
pTable->KeyTable[j].wKeyCtl |= 0x8000; // enable on-fly
|
|
|
|
pKey->bKeyValid = true;
|
|
pKey->uKeyLength = uKeyLength;
|
|
pKey->dwKeyIndex = dwKeyIndex;
|
|
pKey->byCipherSuite = byKeyDecMode;
|
|
memcpy(pKey->abyKey, pbyKey, uKeyLength);
|
|
if (byKeyDecMode == KEY_CTL_WEP) {
|
|
if (uKeyLength == WLAN_WEP40_KEYLEN)
|
|
pKey->abyKey[15] &= 0x7F;
|
|
if (uKeyLength == WLAN_WEP104_KEYLEN)
|
|
pKey->abyKey[15] |= 0x80;
|
|
}
|
|
MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
|
|
|
|
if ((dwKeyIndex & USE_KEYRSC) == 0) {
|
|
// RSC set by NIC
|
|
memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
|
|
} else {
|
|
memcpy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD));
|
|
}
|
|
pKey->dwTSC47_16 = 0;
|
|
pKey->wTSC15_0 = 0;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(N): \n");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
|
|
for (ii = 0; ii < pKey->uKeyLength; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Description: Remove Key from table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* pbyBSSID - BSSID of Key
|
|
* dwKeyIndex - Key Index (reference to NDIS DDK)
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if success otherwise false
|
|
*
|
|
*/
|
|
bool KeybRemoveKey(
|
|
PSKeyManagement pTable,
|
|
unsigned char *pbyBSSID,
|
|
unsigned long dwKeyIndex,
|
|
unsigned long dwIoBase
|
|
)
|
|
{
|
|
int i;
|
|
|
|
if (is_broadcast_ether_addr(pbyBSSID)) {
|
|
// delete all keys
|
|
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
|
|
}
|
|
s_vCheckKeyTableValid(pTable, dwIoBase);
|
|
return true;
|
|
} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
|
|
if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
|
|
// remove Group transmit key
|
|
pTable->KeyTable[i].dwGTKeyIndex = 0;
|
|
}
|
|
}
|
|
s_vCheckKeyTableValid(pTable, dwIoBase);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
|
|
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
|
|
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
|
|
s_vCheckKeyTableValid(pTable, dwIoBase);
|
|
return true;
|
|
} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
|
|
pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
|
|
if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
|
|
// remove Group transmit key
|
|
pTable->KeyTable[i].dwGTKeyIndex = 0;
|
|
}
|
|
s_vCheckKeyTableValid(pTable, dwIoBase);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Description: Remove Key from table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* pbyBSSID - BSSID of Key
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if success otherwise false
|
|
*
|
|
*/
|
|
bool KeybRemoveAllKey(
|
|
PSKeyManagement pTable,
|
|
unsigned char *pbyBSSID,
|
|
unsigned long dwIoBase
|
|
)
|
|
{
|
|
int i, u;
|
|
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
|
|
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
|
|
for (u = 0; u < MAX_GROUP_KEY; u++) {
|
|
pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
|
|
}
|
|
pTable->KeyTable[i].dwGTKeyIndex = 0;
|
|
s_vCheckKeyTableValid(pTable, dwIoBase);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Description: Remove WEP Key from table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if success otherwise false
|
|
*
|
|
*/
|
|
void KeyvRemoveWEPKey(
|
|
PSKeyManagement pTable,
|
|
unsigned long dwKeyIndex,
|
|
unsigned long dwIoBase
|
|
)
|
|
{
|
|
if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
|
|
if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse == true) {
|
|
if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) {
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
|
|
if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) {
|
|
// remove Group transmit key
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0;
|
|
}
|
|
}
|
|
}
|
|
s_vCheckKeyTableValid(pTable, dwIoBase);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void KeyvRemoveAllWEPKey(
|
|
PSKeyManagement pTable,
|
|
unsigned long dwIoBase
|
|
)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_GROUP_KEY; i++) {
|
|
KeyvRemoveWEPKey(pTable, i, dwIoBase);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Description: Get Transmit Key from table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* pbyBSSID - BSSID of Key
|
|
* Out:
|
|
* pKey - Key return
|
|
*
|
|
* Return Value: true if found otherwise false
|
|
*
|
|
*/
|
|
bool KeybGetTransmitKey(
|
|
PSKeyManagement pTable,
|
|
unsigned char *pbyBSSID,
|
|
unsigned long dwKeyType,
|
|
PSKeyItem *pKey
|
|
)
|
|
{
|
|
int i, ii;
|
|
|
|
*pKey = NULL;
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
|
|
if (dwKeyType == PAIRWISE_KEY) {
|
|
if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
|
|
*pKey = &(pTable->KeyTable[i].PairwiseKey);
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PAIRWISE_KEY: KeyTable.abyBSSID: ");
|
|
for (ii = 0; ii < 6; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x ", pTable->KeyTable[i].abyBSSID[ii]);
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
|
|
return true;
|
|
} else {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PairwiseKey.bKeyValid == false\n");
|
|
return false;
|
|
}
|
|
} // End of Type == PAIRWISE
|
|
else {
|
|
if (pTable->KeyTable[i].dwGTKeyIndex == 0) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: dwGTKeyIndex == 0 !!!\n");
|
|
return false;
|
|
}
|
|
if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == true) {
|
|
*pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]);
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP_KEY: KeyTable.abyBSSID\n");
|
|
for (ii = 0; ii < 6; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x ", pTable->KeyTable[i].abyBSSID[ii]);
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex);
|
|
|
|
return true;
|
|
} else {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GroupKey.bKeyValid == false\n");
|
|
return false;
|
|
}
|
|
} // End of Type = GROUP
|
|
} // BSSID match
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: NO Match BSSID !!! ");
|
|
for (ii = 0; ii < 6; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *(pbyBSSID+ii));
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Description: Check Pairewise Key
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if found otherwise false
|
|
*
|
|
*/
|
|
bool KeybCheckPairewiseKey(
|
|
PSKeyManagement pTable,
|
|
PSKeyItem *pKey
|
|
)
|
|
{
|
|
int i;
|
|
|
|
*pKey = NULL;
|
|
for (i = 0; i < MAX_KEY_TABLE; i++) {
|
|
if ((pTable->KeyTable[i].bInUse == true) &&
|
|
(pTable->KeyTable[i].PairwiseKey.bKeyValid == true)) {
|
|
*pKey = &(pTable->KeyTable[i].PairwiseKey);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Description: Set Key to table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* dwKeyIndex - Key index (reference to NDIS DDK)
|
|
* uKeyLength - Key length
|
|
* KeyRSC - Key RSC
|
|
* pbyKey - Pointer to key
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if success otherwise false
|
|
*
|
|
*/
|
|
bool KeybSetDefaultKey(
|
|
PSKeyManagement pTable,
|
|
unsigned long dwKeyIndex,
|
|
unsigned long uKeyLength,
|
|
PQWORD pKeyRSC,
|
|
unsigned char *pbyKey,
|
|
unsigned char byKeyDecMode,
|
|
unsigned long dwIoBase,
|
|
unsigned char byLocalID
|
|
)
|
|
{
|
|
unsigned int ii;
|
|
PSKeyItem pKey;
|
|
unsigned int uKeyIdx;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetDefaultKey: %1x, %d \n", (int)dwKeyIndex, (int)uKeyLength);
|
|
|
|
if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key
|
|
return false;
|
|
} else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
|
|
return false;
|
|
}
|
|
|
|
if (uKeyLength > MAX_KEY_LEN)
|
|
return false;
|
|
|
|
pTable->KeyTable[MAX_KEY_TABLE - 1].bInUse = true;
|
|
for (ii = 0; ii < ETH_ALEN; ii++)
|
|
pTable->KeyTable[MAX_KEY_TABLE - 1].abyBSSID[ii] = 0xFF;
|
|
|
|
// Group key
|
|
pKey = &(pTable->KeyTable[MAX_KEY_TABLE - 1].GroupKey[dwKeyIndex & 0x000000FF]);
|
|
if ((dwKeyIndex & TRANSMIT_KEY) != 0) {
|
|
// Group transmit key
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1);
|
|
|
|
}
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4);
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode);
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044; // use group key for all address
|
|
uKeyIdx = (dwKeyIndex & 0x000000FF);
|
|
|
|
if ((uKeyLength == WLAN_WEP232_KEYLEN) &&
|
|
(byKeyDecMode == KEY_CTL_WEP)) {
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000; // disable on-fly disable address match
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true;
|
|
} else {
|
|
if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == false)
|
|
pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000; // enable on-fly disable address match
|
|
}
|
|
|
|
pKey->bKeyValid = true;
|
|
pKey->uKeyLength = uKeyLength;
|
|
pKey->dwKeyIndex = dwKeyIndex;
|
|
pKey->byCipherSuite = byKeyDecMode;
|
|
memcpy(pKey->abyKey, pbyKey, uKeyLength);
|
|
if (byKeyDecMode == KEY_CTL_WEP) {
|
|
if (uKeyLength == WLAN_WEP40_KEYLEN)
|
|
pKey->abyKey[15] &= 0x7F;
|
|
if (uKeyLength == WLAN_WEP104_KEYLEN)
|
|
pKey->abyKey[15] |= 0x80;
|
|
}
|
|
MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
|
|
|
|
if ((dwKeyIndex & USE_KEYRSC) == 0) {
|
|
// RSC set by NIC
|
|
memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
|
|
} else {
|
|
memcpy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD));
|
|
}
|
|
pKey->dwTSC47_16 = 0;
|
|
pKey->wTSC15_0 = 0;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R): \n");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n", pKey->bKeyValid);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: \n");
|
|
for (ii = 0; ii < pKey->uKeyLength; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x", pKey->abyKey[ii]);
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Description: Set Key to table
|
|
*
|
|
* Parameters:
|
|
* In:
|
|
* pTable - Pointer to Key table
|
|
* dwKeyIndex - Key index (reference to NDIS DDK)
|
|
* uKeyLength - Key length
|
|
* KeyRSC - Key RSC
|
|
* pbyKey - Pointer to key
|
|
* Out:
|
|
* none
|
|
*
|
|
* Return Value: true if success otherwise false
|
|
*
|
|
*/
|
|
bool KeybSetAllGroupKey(
|
|
PSKeyManagement pTable,
|
|
unsigned long dwKeyIndex,
|
|
unsigned long uKeyLength,
|
|
PQWORD pKeyRSC,
|
|
unsigned char *pbyKey,
|
|
unsigned char byKeyDecMode,
|
|
unsigned long dwIoBase,
|
|
unsigned char byLocalID
|
|
)
|
|
{
|
|
int i;
|
|
unsigned int ii;
|
|
PSKeyItem pKey;
|
|
unsigned int uKeyIdx;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
|
|
|
|
if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key
|
|
return false;
|
|
} else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < MAX_KEY_TABLE - 1; i++) {
|
|
if (pTable->KeyTable[i].bInUse == true) {
|
|
// found table already exist
|
|
// Group key
|
|
pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
|
|
if ((dwKeyIndex & TRANSMIT_KEY) != 0) {
|
|
// Group transmit key
|
|
pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
|
|
|
|
}
|
|
pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed
|
|
pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
|
|
pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address
|
|
uKeyIdx = (dwKeyIndex & 0x000000FF);
|
|
|
|
pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly
|
|
|
|
pKey->bKeyValid = true;
|
|
pKey->uKeyLength = uKeyLength;
|
|
pKey->dwKeyIndex = dwKeyIndex;
|
|
pKey->byCipherSuite = byKeyDecMode;
|
|
memcpy(pKey->abyKey, pbyKey, uKeyLength);
|
|
if (byKeyDecMode == KEY_CTL_WEP) {
|
|
if (uKeyLength == WLAN_WEP40_KEYLEN)
|
|
pKey->abyKey[15] &= 0x7F;
|
|
if (uKeyLength == WLAN_WEP104_KEYLEN)
|
|
pKey->abyKey[15] |= 0x80;
|
|
}
|
|
MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
|
|
|
|
if ((dwKeyIndex & USE_KEYRSC) == 0) {
|
|
// RSC set by NIC
|
|
memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
|
|
} else {
|
|
memcpy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD));
|
|
}
|
|
pKey->dwTSC47_16 = 0;
|
|
pKey->wTSC15_0 = 0;
|
|
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R): \n");
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
|
|
for (ii = 0; ii < pKey->uKeyLength; ii++) {
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
|
|
}
|
|
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
|
|
|
|
//DBG_PRN_GRP12(("pKey->dwTSC47_16: %lX\n ", pKey->dwTSC47_16));
|
|
//DBG_PRN_GRP12(("pKey->wTSC15_0: %X\n ", pKey->wTSC15_0));
|
|
//DBG_PRN_GRP12(("pKey->dwKeyIndex: %lX\n ", pKey->dwKeyIndex));
|
|
|
|
} // (pTable->KeyTable[i].bInUse == true)
|
|
}
|
|
return true;
|
|
}
|