M7350/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk_hapd.c
2024-09-09 08:59:52 +00:00

1514 lines
47 KiB
C
Executable File

/*
* WPA PSK handling routines
*
* $Id: 8192cd_psk.c,v 1.6 2010/03/10 03:24:40 keith_huang Exp $
*
* Copyright (c) 2009 Realtek Semiconductor Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define _8192CD_PSK_C_
#ifdef __KERNEL__
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/timer.h>
#include <linux/random.h>
#endif
#include "./8192cd_cfg.h"
#if (defined(WIFI_HAPD) && !defined(HAPD_DRV_PSK_WPS)) || defined(RTK_NL80211)
#include "./8192cd.h"
#include "./wifi.h"
#include "./8192cd_util.h"
#include "./8192cd_headers.h"
#include "./8192cd_security.h"
#include "./ieee802_mib.h"
#include "./8192cd_debug.h"
#include "./8192cd_psk.h"
#include "./1x_rc4.h"
#ifndef __KERNEL__
#include "./sys-support.h"
#endif
//#define DEBUG_PSK
#define ETHER_ADDRLEN 6
#define PMK_EXPANSION_CONST "Pairwise key expansion"
#define PMK_EXPANSION_CONST_SIZE 22
#ifdef RTL_WPA2
#define PMKID_NAME_CONST "PMK Name"
#define PMKID_NAME_CONST_SIZE 8
#endif /* RTL_WPA2 */
#define GMK_EXPANSION_CONST "Group key expansion"
#define GMK_EXPANSION_CONST_SIZE 19
#define RANDOM_EXPANSION_CONST "Init Counter"
#define RANDOM_EXPANSION_CONST_SIZE 12
#define PTK_LEN_CCMP 48
/*
2008-12-16, For Corega CG-WLCB54GL 54Mbps NIC interoperability issue.
The behavior of this NIC when it connect to the other AP with WPA/TKIP is:
AP <----------------------> STA
....................
------------> Assoc Rsp (ok)
------------> EAPOL-key (4-way msg 1)
<------------ unknown TKIP encryption data
------------> EAPOL-key (4-way msg 1)
<------------ unknown TKIP encryption data
.....................
<------------ disassoc (code=8, STA is leaving) when the 5 seconds timer timeout counting from Assoc_Rsp is got.
....................
------------> Assoc Rsp (ok)
<-----------> EAPOL-key (4-way handshake success)
If MAX_RESEND_NUM=3, our AP will send disassoc (code=15, 4-way timeout) to STA before STA sending disassoc to AP.
And this NIC will always can not connect to our AP.
set MAX_RESEND_NUM=5 can fix this issue.
*/
//#define MAX_RESEND_NUM 3
#define MAX_RESEND_NUM 5
#define RESEND_TIME RTL_SECONDS_TO_JIFFIES(1)// in 10ms
#define LargeIntegerOverflow(x) (x.field.HighPart == 0xffffffff) && \
(x.field.LowPart == 0xffffffff)
#define LargeIntegerZero(x) memset(&x.charData, 0, 8);
#define Octet16IntegerOverflow(x) LargeIntegerOverflow(x.field.HighPart) && \
LargeIntegerOverflow(x.field.LowPart)
#define Octet16IntegerZero(x) memset(&x.charData, 0, 16);
#if defined(CONFIG_RTL8186_KB_N)
int authRes = 0;//0: success; 1: fail
#endif
extern void hmac_sha(
unsigned char* k, /* secret key */
int lk, /* length of the key in bytes */
unsigned char* d, /* data */
int ld, /* length of data in bytes */
unsigned char* out, /* output buffer, at least "t" bytes */
int t
);
extern void hmac_sha1(unsigned char *text, int text_len, unsigned char *key,
int key_len, unsigned char *digest);
extern void hmac_md5(unsigned char *text, int text_len, unsigned char *key,
int key_len, void * digest);
#ifdef RTL_WPA2
extern void AES_WRAP(unsigned char *plain, int plain_len,
unsigned char *iv, int iv_len,
unsigned char *kek, int kek_len,
unsigned char *cipher, unsigned short *cipher_len);
#endif
#ifdef DEBUG_PSK
static char *ID2STR(int id)
{
switch(id) {
case DOT11_EVENT_ASSOCIATION_IND:
return("DOT11_EVENT_ASSOCIATION_IND");
case DOT11_EVENT_REASSOCIATION_IND:
return ("DOT11_EVENT_REASSOCIATION_IND");
case DOT11_EVENT_DISASSOCIATION_IND:
return ("DOT11_EVENT_DISASSOCIATION_IND");
case DOT11_EVENT_EAP_PACKET:
return ("DOT11_EVENT_EAP_PACKET");
case DOT11_EVENT_MIC_FAILURE:
return ("DOT11_EVENT_MIC_FAILURE");
default:
return ("Not support event");
}
}
#endif // DEBUG_PSK
static OCTET_STRING SubStr(OCTET_STRING f, unsigned short s, unsigned short l)
{
OCTET_STRING res;
res.Length = l;
res.Octet = f.Octet+s;
return res;
}
static void i_P_SHA1(
unsigned char* key, // pointer to authentication key
int key_len, // length of authentication key
unsigned char* text, // pointer to data stream
int text_len, // length of data stream
unsigned char* digest, // caller digest to be filled in
int digest_len // in byte
)
{
int i;
int offset=0;
int step=20;
int IterationNum=(digest_len+step-1)/step;
for(i=0;i<IterationNum;i++)
{
text[text_len]=(unsigned char)i;
hmac_sha(key,key_len,text,text_len+1,digest+offset,step);
offset+=step;
}
}
static void i_PRF(
unsigned char* secret,
int secret_len,
unsigned char* prefix,
int prefix_len,
unsigned char* random,
int random_len,
unsigned char* digest, // caller digest to be filled in
int digest_len // in byte
)
{
unsigned char data[1000];
memcpy(data,prefix,prefix_len);
data[prefix_len++]=0;
memcpy(data+prefix_len,random,random_len);
i_P_SHA1(secret,secret_len,data,prefix_len+random_len,digest,digest_len);
}
/*
* F(P, S, c, i) = U1 xor U2 xor ... Uc
* U1 = PRF(P, S || Int(i))
* U2 = PRF(P, U1)
* Uc = PRF(P, Uc-1)
*/
static void F(
char *password,
int passwordlength,
unsigned char *ssid,
int ssidlength,
int iterations,
int count,
unsigned char *output)
{
unsigned char digest[36], digest1[A_SHA_DIGEST_LEN];
int i, j;
/* U1 = PRF(P, S || int(i)) */
memcpy(digest, ssid, ssidlength);
digest[ssidlength] = (unsigned char)((count>>24) & 0xff);
digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff);
digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff);
digest[ssidlength+3] = (unsigned char)(count & 0xff);
hmac_sha1(digest, ssidlength + 4,
(unsigned char*) password, (int)strlen(password),
digest1);
/*
hmac_sha1((unsigned char*) password, passwordlength,
digest, ssidlength+4, digest1);
*/
/* output = U1 */
memcpy(output, digest1, A_SHA_DIGEST_LEN);
for (i = 1; i < iterations; i++) {
/* Un = PRF(P, Un-1) */
hmac_sha1(digest1, A_SHA_DIGEST_LEN, (unsigned char*) password,
(int)strlen(password), digest);
//hmac_sha1((unsigned char*) password, passwordlength,digest1, A_SHA_DIGEST_LEN, digest);
memcpy(digest1, digest, A_SHA_DIGEST_LEN);
/* output = output xor Un */
for (j = 0; j < A_SHA_DIGEST_LEN; j++) {
output[j] ^= digest[j];
}
}
}
/*
* password - ascii string up to 63 characters in length
* ssid - octet string up to 32 octets
* ssidlength - length of ssid in octets
* output must be 40 octets in length and outputs 256 bits of key
*/
static int PasswordHash (
char *password,
unsigned char *ssid,
short ssidlength,
unsigned char *output)
{
int passwordlength = strlen(password);
// int ssidlength = strlen(ssid);
if ((passwordlength > 63) || (ssidlength > 32))
return 0;
F(password, passwordlength, ssid, ssidlength, 4096, 1, output);
F(password, passwordlength, ssid, ssidlength, 4096, 2, &output[A_SHA_DIGEST_LEN]);
return 1;
}
void nl80211_ConstructIE(struct rtl8192cd_priv *priv, unsigned char *pucOut, int *usOutLen)
{
DOT11_RSN_IE_HEADER dot11RSNIEHeader = { 0 };
DOT11_RSN_IE_SUITE dot11RSNGroupSuite;
DOT11_RSN_IE_COUNT_SUITE *pDot11RSNPairwiseSuite = NULL;
DOT11_RSN_IE_COUNT_SUITE *pDot11RSNAuthSuite = NULL;
#ifdef CONFIG_IEEE80211W
DOT11_RSN_IE_SUITE dot11RSNIGTKSuite;
#endif
unsigned short usSuitCount;
unsigned long ulIELength = 0;
unsigned long ulIndex = 0;
unsigned long ulPairwiseLength = 0;
unsigned long ulAuthLength = 0;
unsigned char *pucBlob;
DOT11_RSN_IE_COUNT_SUITE countSuite, authCountSuite;
#ifdef RTL_WPA2
DOT11_RSN_CAPABILITY dot11RSNCapability = { 0 };
unsigned long uCipherAlgo = 0;
int bCipherAlgoEnabled = FALSE;
unsigned long uAuthAlgo = 0;
int bAuthAlgoEnabled = FALSE;
unsigned long ulRSNCapabilityLength = 0;
#endif
*usOutLen = 0;
if ( priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) {
//
// Construct Information Header
//
dot11RSNIEHeader.ElementID = RSN_ELEMENT_ID;
dot11RSNIEHeader.OUI[0] = 0x00;
dot11RSNIEHeader.OUI[1] = 0x50;
dot11RSNIEHeader.OUI[2] = 0xf2;
dot11RSNIEHeader.OUI[3] = 0x01;
dot11RSNIEHeader.Version = cpu_to_le16(RSN_VER1);
ulIELength += sizeof(DOT11_RSN_IE_HEADER);
// Construct Cipher Suite:
// - Multicast Suite:
memset(&dot11RSNGroupSuite, 0, sizeof dot11RSNGroupSuite);
dot11RSNGroupSuite.OUI[0] = 0x00;
dot11RSNGroupSuite.OUI[1] = 0x50;
dot11RSNGroupSuite.OUI[2] = 0xF2;
dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher;
ulIELength += sizeof(DOT11_RSN_IE_SUITE);
// - UnicastSuite
pDot11RSNPairwiseSuite = &countSuite;
memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE));
usSuitCount = 0;
#ifdef RTK_NL80211
for (ulIndex=0; ulIndex<priv->wpa_global_info->NumOfUnicastCipher; ulIndex++)
{
int i = ulIndex<priv->wpa_global_info->NumOfUnicastCipher - ulIndex - 1;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[i];
usSuitCount++;
}
#else
for (ulIndex=0; ulIndex<priv->wpa_global_info->NumOfUnicastCipher; ulIndex++)
{
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[ulIndex];
usSuitCount++;
}
#endif
pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount);
ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE);
ulIELength += ulPairwiseLength;
//
// Construction of Auth Algo List
//
pDot11RSNAuthSuite = &authCountSuite;
memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE));
usSuitCount = 0;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK;
usSuitCount++;
pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount);
ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE);
ulIELength += ulAuthLength;
//---------------------------------------------------------------------------------------------
// Do not encapsulate capability field to solve TI WPA issue
//---------------------------------------------------------------------------------------------
/*
dot11RSNCapability.field.PreAuthentication = 0;//auth->RSNVariable.isSupportPreAuthentication
dot11RSNCapability.field.PairwiseAsDefaultKey = auth->RSNVariable.isSupportPairwiseAsDefaultKey;
switch(auth->RSNVariable.NumOfRxTSC)
{
case 1:
dot11RSNCapability.field.NumOfReplayCounter = 0;
break;
case 2:
dot11RSNCapability.field.NumOfReplayCounter = 1;
break;
case 4:
dot11RSNCapability.field.NumOfReplayCounter = 2;
break;
case 16:
dot11RSNCapability.field.NumOfReplayCounter = 3;
break;
default:
dot11RSNCapability.field.NumOfReplayCounter = 0;
}
ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY);
ulIELength += ulRSNCapabilityLength;
*/
pucBlob = pucOut;
pucBlob += sizeof(DOT11_RSN_IE_HEADER);
memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE));
pucBlob += sizeof(DOT11_RSN_IE_SUITE);
memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength);
pucBlob += ulPairwiseLength;
memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength);
pucBlob += ulAuthLength;
*usOutLen = (int)ulIELength;
pucBlob = pucOut;
dot11RSNIEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header
memcpy(pucBlob, &dot11RSNIEHeader, sizeof(DOT11_RSN_IE_HEADER));
}
#ifdef RTL_WPA2
if ( priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2 ) {
DOT11_WPA2_IE_HEADER dot11WPA2IEHeader = { 0 };
ulIELength = 0;
ulIndex = 0;
ulPairwiseLength = 0;
uCipherAlgo = 0;
bCipherAlgoEnabled = FALSE;
ulAuthLength = 0;
uAuthAlgo = 0;
bAuthAlgoEnabled = FALSE;
ulRSNCapabilityLength = 0;
//
// Construct Information Header
//
dot11WPA2IEHeader.ElementID = WPA2_ELEMENT_ID;
dot11WPA2IEHeader.Version = cpu_to_le16(RSN_VER1);
ulIELength += sizeof(DOT11_WPA2_IE_HEADER);
// Construct Cipher Suite:
// - Multicast Suite:
//
memset(&dot11RSNGroupSuite, 0, sizeof(dot11RSNGroupSuite));
dot11RSNGroupSuite.OUI[0] = 0x00;
dot11RSNGroupSuite.OUI[1] = 0x0F;
dot11RSNGroupSuite.OUI[2] = 0xAC;
dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher;;
ulIELength += sizeof(DOT11_RSN_IE_SUITE);
// - UnicastSuite
pDot11RSNPairwiseSuite = &countSuite;
memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE));
usSuitCount = 0;
#ifdef RTK_NL80211
for (ulIndex=0; ulIndex<priv->wpa_global_info->NumOfUnicastCipherWPA2; ulIndex++)
{
int i = priv->wpa_global_info->NumOfUnicastCipherWPA2 - ulIndex - 1;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[i];
usSuitCount++;
}
#else
for (ulIndex=0; ulIndex<priv->wpa_global_info->NumOfUnicastCipherWPA2; ulIndex++)
{
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC;
pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[ulIndex];
usSuitCount++;
}
#endif
pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount);
ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE);
ulIELength += ulPairwiseLength;
//
// Construction of Auth Algo List
//
pDot11RSNAuthSuite = &authCountSuite;
memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE));
usSuitCount = 0;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC;
if (OPMODE & WIFI_AP_STATE)
{
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED)
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256;
else
#endif
{
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK;
}
usSuitCount++;
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL
&& priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == 1) {
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC;
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256;
usSuitCount++;
}
#endif
} else {
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != 0
&& priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == 1)
{
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256;
}
else
#endif
{
pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK;
}
usSuitCount++;
}
pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount);
ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE);
ulIELength += ulAuthLength;
//---------------------------------------------------------------------------------------------
// Do not encapsulate capability field to solve TI WPA issue
//---------------------------------------------------------------------------------------------
//#ifdef RTL_WPA2
#if 1
dot11RSNCapability.field.PreAuthentication = 0;
#else
dot11RSNCapability.field.PairwiseAsDefaultKey = auth->RSNVariable.isSupportPairwiseAsDefaultKey;
switch(auth->RSNVariable.NumOfRxTSC)
{
case 1:
dot11RSNCapability.field.NumOfReplayCounter = 0;
break;
case 2:
dot11RSNCapability.field.NumOfReplayCounter = 1;
break;
case 4:
dot11RSNCapability.field.NumOfReplayCounter = 2;
break;
case 16:
dot11RSNCapability.field.NumOfReplayCounter = 3;
break;
default:
dot11RSNCapability.field.NumOfReplayCounter = 0;
}
#endif
#if (defined(WIFI_HAPD) & defined(WIFI_WMM)) || (defined(RTK_NL80211) & defined(WIFI_WMM)) //eric-wds
if(QOS_ENABLE){
/* 4 PTKSA replay counters when using WMM consistent with hostapd code*/
dot11RSNCapability.field.PtksaReplayCounter = 3;
}
#endif
#ifdef CONFIG_IEEE80211W
//Protected Managemenet Protection Capability (PMF)
//printk("ConstructIE, dot11IEEE80211W=%d\n", priv->pmib->dot1180211AuthEntry.dot11IEEE80211W);
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION) {
dot11RSNCapability.field.MFPC = 0;
dot11RSNCapability.field.MFPR = 0;
} else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL)
dot11RSNCapability.field.MFPC = 1; // MFPC
else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
dot11RSNCapability.field.MFPR = 1; // MFPR
dot11RSNCapability.field.MFPC = 1; // MFPC
}
#endif
ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY);
ulIELength += ulRSNCapabilityLength;
#ifdef CONFIG_IEEE80211W
// Construct Cipher Suite:
// - IGTK Suite:
//
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W /*&& priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == TRUE*/) {
memset(&dot11RSNIGTKSuite, 0, sizeof(dot11RSNIGTKSuite));
dot11RSNIGTKSuite.OUI[0] = 0x00;
dot11RSNIGTKSuite.OUI[1] = 0x0F;
dot11RSNIGTKSuite.OUI[2] = 0xAC;
dot11RSNIGTKSuite.Type = DOT11_ENC_BIP;
ulIELength += sizeof(dot11RSNIGTKSuite) + 2;
}
#endif // CONFIG_IEEE80211W
pucBlob = pucOut + *usOutLen;
pucBlob += sizeof(DOT11_WPA2_IE_HEADER);
memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE));
pucBlob += sizeof(DOT11_RSN_IE_SUITE);
memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength);
pucBlob += ulPairwiseLength;
memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength);
pucBlob += ulAuthLength;
memcpy(pucBlob, &dot11RSNCapability, ulRSNCapabilityLength);
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) {
pucBlob += ulRSNCapabilityLength + 2; // add PMKID Count (2bytes)
memcpy(pucBlob, &dot11RSNIGTKSuite, sizeof(DOT11_RSN_IE_SUITE));
}
#endif // CONFIG_IEEE80211W
pucBlob = pucOut + *usOutLen;
dot11WPA2IEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header
memcpy(pucBlob, &dot11WPA2IEHeader, sizeof(DOT11_WPA2_IE_HEADER));
*usOutLen = *usOutLen + (int)ulIELength;
}
#endif // RTL_WPA2
}
static int MIN(unsigned char *ucStr1, unsigned char *ucStr2, unsigned long ulLen)
{
int i;
for (i=0 ; i<ulLen ; i++) {
if ((unsigned char)ucStr1[i] < (unsigned char)ucStr2[i])
return -1;
else if((unsigned char)ucStr1[i] > (unsigned char)ucStr2[i])
return 1;
else if(i == ulLen - 1)
return 0;
else
continue;
}
return 0;
}
static int parseIE(struct rtl8192cd_priv *priv, WPA_STA_INFO *pInfo,
unsigned char *pucIE, unsigned long ulIELength)
{
unsigned short usSuitCount;
DOT11_RSN_IE_HEADER *pDot11RSNIEHeader;
DOT11_RSN_IE_SUITE *pDot11RSNIESuite;
DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite;
DOT11_RSN_CAPABILITY * pDot11RSNCapability = NULL;
DEBUG_TRACE;
if (ulIELength < sizeof(DOT11_RSN_IE_HEADER)) {
DEBUG_WARN("parseIE err 1!\n");
return ERROR_INVALID_RSNIE;
}
pDot11RSNIEHeader = (DOT11_RSN_IE_HEADER *)pucIE;
if (le16_to_cpu(pDot11RSNIEHeader->Version) != RSN_VER1) {
DEBUG_WARN("parseIE err 2!\n");
return ERROR_UNSUPPORTED_RSNEVERSION;
}
if (pDot11RSNIEHeader->ElementID != RSN_ELEMENT_ID ||
pDot11RSNIEHeader->Length != ulIELength -2 ||
pDot11RSNIEHeader->OUI[0] != 0x00 || pDot11RSNIEHeader->OUI[1] != 0x50 ||
pDot11RSNIEHeader->OUI[2] != 0xf2 || pDot11RSNIEHeader->OUI[3] != 0x01 ) {
DEBUG_WARN("parseIE err 3!\n");
return ERROR_INVALID_RSNIE;
}
pInfo->RSNEnabled= PSK_WPA; // wpa
ulIELength -= sizeof(DOT11_RSN_IE_HEADER);
pucIE += sizeof(DOT11_RSN_IE_HEADER);
//----------------------------------------------------------------------------------
// Multicast Cipher Suite processing
//----------------------------------------------------------------------------------
if (ulIELength < sizeof(DOT11_RSN_IE_SUITE))
return 0;
pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE;
if (pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x50 ||
pDot11RSNIESuite->OUI[2] != 0xF2) {
DEBUG_WARN("parseIE err 4!\n");
return ERROR_INVALID_RSNIE;
}
if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) {
DEBUG_WARN("parseIE err 5!\n");
return ERROR_INVALID_MULTICASTCIPHER;
}
if (pDot11RSNIESuite->Type != priv->wpa_global_info->MulticastCipher) {
DEBUG_WARN("parseIE err 6!\n");
return ERROR_INVALID_MULTICASTCIPHER;
}
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
if (pDot11RSNIESuite->Type != DOT11_ENC_CCMP) {
PMFDEBUG("Invalid WPA group cipher %d\n", pDot11RSNIESuite->Type);
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
}
#endif
ulIELength -= sizeof(DOT11_RSN_IE_SUITE);
pucIE += sizeof(DOT11_RSN_IE_SUITE);
//----------------------------------------------------------------------------------
// Pairwise Cipher Suite processing
//----------------------------------------------------------------------------------
if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE))
return 0;
pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE;
pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite;
usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount);
if (usSuitCount != 1 ||
pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x50 ||
pDot11RSNIESuite->OUI[2] != 0xF2) {
DEBUG_WARN("parseIE err 7!\n");
return ERROR_INVALID_RSNIE;
}
if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) {
DEBUG_WARN("parseIE err 8!\n");
return ERROR_INVALID_UNICASTCIPHER;
}
if ((pDot11RSNIESuite->Type < DOT11_ENC_WEP40)
|| (!(BIT(pDot11RSNIESuite->Type - 1) & priv->pmib->dot1180211AuthEntry.dot11WPACipher))) {
DEBUG_WARN("parseIE err 9!\n");
return ERROR_INVALID_UNICASTCIPHER;
}
pInfo->UnicastCipher = pDot11RSNIESuite->Type;
#ifdef DEBUG_PSK
printk("PSK: ParseIE -> WPA UnicastCipher=%x\n", pInfo->UnicastCipher);
#endif
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
if (pInfo->UnicastCipher == DOT11_ENC_TKIP) {
PMFDEBUG("Management frame protection cannot use TKIP\n");
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
}
#endif
ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
//----------------------------------------------------------------------------------
// Authentication suite
//----------------------------------------------------------------------------------
if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE))
return 0;
pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE;
pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite;
usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount);
if (usSuitCount != 1 ||
pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x50 ||
pDot11RSNIESuite->OUI[2] != 0xF2 ) {
DEBUG_WARN("parseIE err 10!\n");
return ERROR_INVALID_RSNIE;
}
if( pDot11RSNIESuite->Type < DOT11_AuthKeyType_RSN ||
pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK) {
DEBUG_WARN("parseIE err 11!\n");
return ERROR_INVALID_AUTHKEYMANAGE;
}
if(pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK) {
DEBUG_WARN("parseIE err 12!\n");
return ERROR_INVALID_AUTHKEYMANAGE;
}
//pInfo->AuthKeyMethod = pDot11RSNIESuite->Type;
ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
// RSN Capability
if (ulIELength < sizeof(DOT11_RSN_CAPABILITY))
return 0;
//#ifndef RTL_WPA2
#if 0
//----------------------------------------------------------------------------------
// Capability field
//----------------------------------------------------------------------------------
pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE;
pInfo->isSuppSupportPreAuthentication = pDot11RSNCapability->field.PreAuthentication;
pInfo->isSuppSupportPairwiseAsDefaultKey = pDot11RSNCapability->field.PairwiseAsDefaultKey;
switch (pDot11RSNCapability->field.NumOfReplayCounter) {
case 0:
pInfo->NumOfRxTSC = 1;
break;
case 1:
pInfo->NumOfRxTSC = 2;
break;
case 2:
pInfo->NumOfRxTSC = 4;
break;
case 3:
pInfo->NumOfRxTSC = 16;
break;
default:
pInfo->NumOfRxTSC = 1;
}
#endif /* RTL_WPA2 */
#ifdef CONFIG_IEEE80211W
pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE;
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
if (!pDot11RSNCapability->field.MFPC) {
PMFDEBUG("Management frame protection Required, but client did not enable it\n");
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
}
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION ||
!(pDot11RSNCapability->field.MFPC))
pInfo->mgmt_frame_prot = 0;
else
pInfo->mgmt_frame_prot = 1;
PMFDEBUG("mgmt_frame_prot=%d\n", pInfo->mgmt_frame_prot);
#endif // CONFIG_IEEE80211W
return 0;
}
#ifdef RTL_WPA2
static int parseIEWPA2(struct rtl8192cd_priv *priv, WPA_STA_INFO *pInfo,
unsigned char *pucIE, unsigned long ulIELength)
{
unsigned short usSuitCount;
DOT11_WPA2_IE_HEADER *pDot11WPA2IEHeader = NULL;
DOT11_RSN_IE_SUITE *pDot11RSNIESuite = NULL;
DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite = NULL;
DOT11_RSN_CAPABILITY *pDot11RSNCapability = NULL;
DEBUG_TRACE;
if (ulIELength < sizeof(DOT11_WPA2_IE_HEADER)) {
DEBUG_WARN("ERROR_INVALID_RSNIE, err 1!\n");
return ERROR_INVALID_RSNIE;
}
pDot11WPA2IEHeader = (DOT11_WPA2_IE_HEADER *)pucIE;
if (le16_to_cpu(pDot11WPA2IEHeader->Version) != RSN_VER1) {
DEBUG_WARN("ERROR_UNSUPPORTED_RSNEVERSION, err 2!\n");
return ERROR_UNSUPPORTED_RSNEVERSION;
}
if (pDot11WPA2IEHeader->ElementID != WPA2_ELEMENT_ID ||
pDot11WPA2IEHeader->Length != ulIELength -2 ) {
DEBUG_WARN("ERROR_INVALID_RSNIE, err 3!\n");
return ERROR_INVALID_RSNIE;
}
pInfo->RSNEnabled= PSK_WPA2;
//pInfo->PMKCached= FALSE;
ulIELength -= sizeof(DOT11_WPA2_IE_HEADER);
pucIE += sizeof(DOT11_WPA2_IE_HEADER);
//----------------------------------------------------------------------------------
// Multicast Cipher Suite processing
//----------------------------------------------------------------------------------
if (ulIELength < sizeof(DOT11_RSN_IE_SUITE))
return 0;
pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE;
if (pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x0F ||
pDot11RSNIESuite->OUI[2] != 0xAC) {
DEBUG_WARN("ERROR_INVALID_RSNIE, err 4!\n");
return ERROR_INVALID_RSNIE;
}
#ifdef CONFIG_IEEE80211W
if (pDot11RSNIESuite->Type > DOT11_ENC_BIP)
#else
if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104)
#endif
{
DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 5!\n");
return ERROR_INVALID_MULTICASTCIPHER;
}
if (pDot11RSNIESuite->Type != priv->wpa_global_info->MulticastCipher) {
DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 6!\n");
return ERROR_INVALID_MULTICASTCIPHER;
}
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
if (pDot11RSNIESuite->Type != DOT11_ENC_CCMP) {
DEBUG_WARN("Invalid WPA group cipher %d\n", pDot11RSNIESuite->Type);
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
}
#endif
ulIELength -= sizeof(DOT11_RSN_IE_SUITE);
pucIE += sizeof(DOT11_RSN_IE_SUITE);
//----------------------------------------------------------------------------------
// Pairwise Cipher Suite processing
//----------------------------------------------------------------------------------
if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE))
return 0;
pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE;
pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite;
usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount);
if (usSuitCount != 1 ||
pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x0F ||
pDot11RSNIESuite->OUI[2] != 0xAC) {
DEBUG_WARN("ERROR_INVALID_RSNIE, err 7!\n");
return ERROR_INVALID_RSNIE;
}
if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) {
DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 8!\n");
return ERROR_INVALID_UNICASTCIPHER;
}
if ((pDot11RSNIESuite->Type < DOT11_ENC_WEP40)
|| (!(BIT(pDot11RSNIESuite->Type - 1) & priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher))) {
DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 9!\n");
return ERROR_INVALID_UNICASTCIPHER;
}
pInfo->UnicastCipher = pDot11RSNIESuite->Type;
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
if (pInfo->UnicastCipher == DOT11_ENC_TKIP) {
DEBUG_WARN("Management frame protection cannot use TKIP\n");
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
}
#endif
ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
#ifdef DEBUG_PSK
printk("PSK: ParseIE -> WPA2 UnicastCipher=%x\n", pInfo->UnicastCipher);
#endif
//----------------------------------------------------------------------------------
// Authentication suite
//----------------------------------------------------------------------------------
if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE))
return 0;
pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE;
pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite;
usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount);
if (usSuitCount != 1 ||
pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x0F ||
pDot11RSNIESuite->OUI[2] != 0xAC ) {
DEBUG_WARN("ERROR_INVALID_RSNIE, err 10!\n");
return ERROR_INVALID_RSNIE;
}
if ((pDot11RSNIESuite->Type < DOT11_AuthKeyType_RSN) ||
#ifdef CONFIG_IEEE80211W
(pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK_SHA256)
#else
(pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK)
#endif
) {
DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 11!\n");
return ERROR_INVALID_AUTHKEYMANAGE;
}
if((pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK)
#ifdef CONFIG_IEEE80211W
&& pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK_SHA256
#endif
) {
DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 12!\n");
return ERROR_INVALID_AUTHKEYMANAGE;
}
//pInfo->AuthKeyMethod = pDot11RSNIESuite->Type;
ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE);
// RSN Capability
if (ulIELength < sizeof(DOT11_RSN_CAPABILITY)) {
//pInfo->NumOfRxTSC = 2;
return 0;
}
//----------------------------------------------------------------------------------
// Capability field
//----------------------------------------------------------------------------------
pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE;
#if 0
global->RSNVariable.isSuppSupportPreAuthentication = pDot11RSNCapability->field.PreAuthentication;
//#ifdef RTL_WPA2_PREAUTH // kenny temp
//wpa2_hexdump("WPA2 IE Capability", pucIE, 2);
//global->RSNVariable.isSuppSupportPreAuthentication = (pDot11RSNCapability->charData[0] & 0x01)?TRUE:FALSE;
#endif
#if 1
//pInfo->NumOfRxTSC = 1;
#else
global->RSNVariable.isSuppSupportPairwiseAsDefaultKey = pDot11RSNCapability->field.PairwiseAsDefaultKey;
switch (pDot11RSNCapability->field.NumOfReplayCounter) {
case 0:
global->RSNVariable.NumOfRxTSC = 1;
break;
case 1:
global->RSNVariable.NumOfRxTSC = 2;
break;
case 2:
global->RSNVariable.NumOfRxTSC = 4;
break;
case 3:
global->RSNVariable.NumOfRxTSC = 16;
break;
default:
global->RSNVariable.NumOfRxTSC = 1;
}
#endif
#ifdef CONFIG_IEEE80211W
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) {
if (!pDot11RSNCapability->field.MFPC) {
printk("Management frame protection Required, but client did not enable it\n");
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
}
if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION ||
!(pDot11RSNCapability->field.MFPC))
pInfo->mgmt_frame_prot = 0;
else
pInfo->mgmt_frame_prot = 1;
PMFDEBUG("mgmt_frame_prot=%d\n", pInfo->mgmt_frame_prot);
#endif // CONFIG_IEEE80211W
pucIE += sizeof(DOT11_RSN_CAPABILITY);
ulIELength -= sizeof(DOT11_RSN_CAPABILITY);
// PMKID
if ((ulIELength < 2 + PMKID_LEN))
return 0;
//----------------------------------------------------------------------------------
// PMKID Count field
//----------------------------------------------------------------------------------
usSuitCount = le16_to_cpu(*((unsigned short *)pucIE));
//printf("PMKID Count = %d\n",usSuitCount);
pucIE += 2;
ulIELength -= 2;
/*
if ( usSuitCount > 0) {
struct _WPA2_PMKSA_Node* pmksa_node;
int i;
for (i=0; i < usSuitCount; i++) {
pmksa_node = find_pmksa(pucIE+(PMKID_LEN*i));
if ( pmksa_node != NULL) {
//wpa2_hexdump("Cached PMKID found", pmksa_node->pmksa.pmkid, PMKID_LEN);
global->RSNVariable.PMKCached = TRUE;
global->RSNVariable.cached_pmk_node = pmksa_node;
break;
}
}
}
*/
#ifdef CONFIG_IEEE80211W
pucIE += PMKID_LEN * usSuitCount;
printk("usSuitCount=%d, ulIELength=%d\n", usSuitCount, ulIELength);
ulIELength -= PMKID_LEN * usSuitCount;
//----------------------------------------------------------------------------------
// Group Management Cipher field (IGTK)
//----------------------------------------------------------------------------------
if ((ulIELength < sizeof(DOT11_RSN_IE_SUITE))) {
return 0;
}
pDot11RSNIESuite = (DOT11_RSN_IE_SUITE*)pucIE;
if (pDot11RSNIESuite->OUI[0] != 0x00 ||
pDot11RSNIESuite->OUI[1] != 0x0F ||
pDot11RSNIESuite->OUI[2] != 0xAC) {
printk("RSNIE Suite OUI = %02x:%02x:%02x\n", pDot11RSNIESuite->OUI[0], pDot11RSNIESuite->OUI[1], pDot11RSNIESuite->OUI[2]);
return ERROR_INVALID_RSNIE;
}
if (pDot11RSNIESuite->Type != DOT11_ENC_BIP) {
return ERROR_MGMT_FRAME_PROTECTION_VIOLATION;
}
#endif // CONFIG_IEEE80211W
return 0;
}
#endif // RTL_WPA2
static void ToDrv_RspAssoc(struct rtl8192cd_priv *priv, int id, unsigned char *mac, int status)
{
DOT11_ASSOCIATIIN_RSP Association_Rsp;
struct iw_point wrq;
DEBUG_TRACE;
#ifdef DEBUG_PSK
printk("PSK: Issue assoc-rsp [%x], mac:%02x:%02x:%02x:%02x:%02x:%02x\n",
status, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
#endif
wrq.pointer = (caddr_t)&Association_Rsp;
wrq.length = sizeof(DOT11_ASSOCIATIIN_RSP);
if (id == DOT11_EVENT_ASSOCIATION_IND)
Association_Rsp.EventId = DOT11_EVENT_ASSOCIATION_RSP;
else
Association_Rsp.EventId = DOT11_EVENT_REASSOCIATION_RSP;
Association_Rsp.IsMoreEvent = FALSE;
Association_Rsp.Status = status;
memcpy(Association_Rsp.MACAddr, mac, 6);
rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq);
}
static void ToDrv_RemovePTK(struct rtl8192cd_priv *priv, unsigned char *mac, int type)
{
struct iw_point wrq;
DOT11_DELETE_KEY Delete_Key;
#ifdef DEBUG_PSK
printk("PSK: Remove PTK, mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
#endif
wrq.pointer = (caddr_t)&Delete_Key;
wrq.length = sizeof(DOT11_DELETE_KEY);
Delete_Key.EventId = DOT11_EVENT_DELETE_KEY;
Delete_Key.IsMoreEvent = FALSE;
Delete_Key.KeyType = type;
memcpy(&Delete_Key.MACAddr, mac, 6);
rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq);
}
static void ToDrv_SetPort(struct rtl8192cd_priv *priv, struct stat_info *pstat, int status)
{
struct iw_point wrq;
DOT11_SET_PORT Set_Port;
#ifdef DEBUG_PSK
printk("PSK: Set PORT [%x], mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
status, pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2],
pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]);
#endif
wrq.pointer = (caddr_t)&Set_Port;
wrq.length = sizeof(DOT11_SET_PORT);
Set_Port.EventId = DOT11_EVENT_SET_PORT;
Set_Port.PortStatus = status;
memcpy(&Set_Port.MACAddr, pstat->hwaddr, 6);
rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq);
}
static void ToDrv_SetIE(struct rtl8192cd_priv *priv)
{
struct iw_point wrq;
DOT11_SET_RSNIE Set_Rsnie;
#ifdef DEBUG_PSK
debug_out("PSK: Set RSNIE", priv->wpa_global_info->AuthInfoElement.Octet,
priv->wpa_global_info->AuthInfoElement.Length);
#endif
wrq.pointer = (caddr_t)&Set_Rsnie;
wrq.length = sizeof(DOT11_SET_RSNIE);
Set_Rsnie.EventId = DOT11_EVENT_SET_RSNIE;
Set_Rsnie.IsMoreEvent = FALSE;
Set_Rsnie.Flag = DOT11_Ioctl_Set;
Set_Rsnie.RSNIELen = priv->wpa_global_info->AuthInfoElement.Length;
memcpy(&Set_Rsnie.RSNIE,
priv->wpa_global_info->AuthInfoElement.Octet,
priv->wpa_global_info->AuthInfoElement.Length);
rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq);
}
static void reset_sta_info(struct rtl8192cd_priv *priv, struct stat_info *pstat)
{
WPA_STA_INFO *pInfo = pstat->wpa_sta_info;
#ifndef SMP_SYNC
unsigned long flags;
#endif
SAVE_INT_AND_CLI(flags);
if (OPMODE & WIFI_AP_STATE)
{
ToDrv_RemovePTK(priv, pstat->hwaddr, DOT11_KeyType_Pairwise);
ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Unauthorized);
}
memset((char *)pInfo, '\0', sizeof(WPA_STA_INFO));
pInfo->priv = priv;
if (OPMODE & WIFI_AP_STATE)
{
pInfo->state = PSK_STATE_IDLE;
}
RESTORE_INT(flags);
}
void nl80211_psk_init(struct rtl8192cd_priv *priv)
{
WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info;
int i, j, low_cipher=0;
DEBUG_TRACE;
memset((char *)pGblInfo, '\0', sizeof(WPA_GLOBAL_INFO));
if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) &&
!priv->pmib->dot1180211AuthEntry.dot11WPACipher) {
DEBUG_ERR("psk_init failed, WPA cipher did not set!\n");
return;
}
#ifdef RTL_WPA2
if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) &&
!priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) {
DEBUG_ERR("psk_init failed, WPA2 cipher did not set!\n");
return;
}
#endif
if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) &&
!(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA)) {
if (priv->pmib->dot1180211AuthEntry.dot11WPACipher)
priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0;
}
if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) &&
!(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2)) {
if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher)
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0;
}
if (priv->pmib->dot1180211AuthEntry.dot11WPACipher) {
for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) {
if (priv->pmib->dot1180211AuthEntry.dot11WPACipher & (1<<i)) {
pGblInfo->UnicastCipher[j] = i+1;
if (low_cipher == 0)
low_cipher = pGblInfo->UnicastCipher[j];
else {
if (low_cipher == _WEP_104_PRIVACY_ &&
pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_)
low_cipher = pGblInfo->UnicastCipher[j];
else if (low_cipher == _TKIP_PRIVACY_ &&
(pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_ ||
pGblInfo->UnicastCipher[j] == _WEP_104_PRIVACY_))
low_cipher = pGblInfo->UnicastCipher[j];
else if (low_cipher == _CCMP_PRIVACY_)
low_cipher = pGblInfo->UnicastCipher[j];
}
if (++j >= MAX_UNICAST_CIPHER)
break;
}
}
pGblInfo->NumOfUnicastCipher = j;
}
#ifdef RTL_WPA2
if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) {
for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) {
if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & (1<<i)) {
pGblInfo->UnicastCipherWPA2[j] = i+1;
if (low_cipher == 0)
low_cipher = pGblInfo->UnicastCipherWPA2[j];
else {
if (low_cipher == _WEP_104_PRIVACY_ &&
pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_)
low_cipher = pGblInfo->UnicastCipherWPA2[j];
else if (low_cipher == _TKIP_PRIVACY_ &&
(pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_ ||
pGblInfo->UnicastCipherWPA2[j] == _WEP_104_PRIVACY_))
low_cipher = pGblInfo->UnicastCipherWPA2[j];
else if (low_cipher == _CCMP_PRIVACY_)
low_cipher = pGblInfo->UnicastCipherWPA2[j];
}
if (++j >= MAX_UNICAST_CIPHER)
break;
}
}
pGblInfo->NumOfUnicastCipherWPA2= j;
}
#endif
pGblInfo->MulticastCipher = low_cipher;
#ifdef DEBUG_PSK
printk("PSK: WPA unicast cipher= ");
for (i=0; i<pGblInfo->NumOfUnicastCipher; i++)
printk("%x ", pGblInfo->UnicastCipher[i]);
printk("\n");
#ifdef RTL_WPA2
printk("PSK: WPA2 unicast cipher= ");
for (i=0; i<pGblInfo->NumOfUnicastCipherWPA2; i++)
printk("%x ", pGblInfo->UnicastCipherWPA2[i]);
printk("\n");
#endif
printk("PSK: multicast cipher= %x\n", pGblInfo->MulticastCipher);
#endif
pGblInfo->AuthInfoElement.Octet = pGblInfo->AuthInfoBuf;
nl80211_ConstructIE(priv, pGblInfo->AuthInfoElement.Octet,
&pGblInfo->AuthInfoElement.Length);
ToDrv_SetIE(priv);
}
#if (defined(WIFI_HAPD) || defined(RTK_NL80211)) && defined(WDS)
void wds_psk_set(struct rtl8192cd_priv *priv, int idx, unsigned char *key)
{
#if !defined(WIFI_HAPD) // && !defined(RTK_NL80211)
unsigned char pchar[40];
if (key == NULL) {
if (strlen(priv->pmib->dot11WdsInfo.wdsPskPassPhrase) == 64) // hex
get_array_val(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], priv->pmib->dot11WdsInfo.wdsPskPassPhrase, 64);
else {
memset(pchar, 0, sizeof(unsigned char)*40);
PasswordHash(priv->pmib->dot11WdsInfo.wdsPskPassPhrase,"REALTEK", strlen("REALTEK"), pchar);
memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], pchar, sizeof(unsigned char)*32);
}
}
else
memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], key, sizeof(unsigned char)*32);
priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] = 32;
priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] |= 0x80000000; //set bit to protect the key
#endif
}
void wds_psk_init(struct rtl8192cd_priv *priv)
{
unsigned char *key;
int i;
if ( !(OPMODE & WIFI_AP_STATE))
return;
for (i = 0; i < priv->pmib->dot11WdsInfo.wdsNum; i++) {
if (i==0)
key = NULL;
else
key = priv->pmib->dot11WdsInfo.wdsMapingKey[0];
wds_psk_set(priv, i, key);
}
}
void hapd_set_wdskey(struct net_device *dev, char *wdsPskPassPhrase, char *ssid, int wds_num)
{
struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev);
int idx = 0;
unsigned char pchar[40];
memcpy(priv->pmib->dot11WdsInfo.wdsPskPassPhrase, wdsPskPassPhrase, strlen(wdsPskPassPhrase));
priv->pmib->dot11WdsInfo.wdsPskPassPhrase[strlen(wdsPskPassPhrase)] = '\0';
memset(pchar, 0, sizeof(unsigned char)*40);
PasswordHash(wdsPskPassPhrase, ssid, strlen(ssid), pchar);
for(idx =0; idx<wds_num; idx++)
{
memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], pchar, sizeof(unsigned char)*32);
priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] = 32;
priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] |= 0x80000000; //set bit to protect the key
}
}
#endif
int nl80211_psk_indicate_evt(struct rtl8192cd_priv *priv, int id, unsigned char *mac, unsigned char *msg, int len)
{
struct stat_info *pstat;
unsigned char tmpbuf[1024];
int ret;
#ifdef RTL_WPA2
int isWPA2=0;
#endif
if (!priv->pmib->dot1180211AuthEntry.dot11EnablePSK ||
!((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) ||
(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)))
return -1;
#ifdef DEBUG_PSK
printk("PSK: Got evt:%s[%x], sta: %02x:%02x:%02x:%02x:%02x:%02x, msg_len=%x\n",
ID2STR(id), id,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], len);
#endif
pstat = get_stainfo(priv, mac);
// button 2009.05.21
#if 0
if (pstat == NULL)
#else
if (pstat == NULL && id!=DOT11_EVENT_WPA_MULTICAST_CIPHER && id!=DOT11_EVENT_WPA2_MULTICAST_CIPHER)
#endif
{
DEBUG_ERR("Invalid mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return -1;
}
switch (id) {
case DOT11_EVENT_ASSOCIATION_IND:
case DOT11_EVENT_REASSOCIATION_IND:
reset_sta_info(priv, pstat);
if (OPMODE & WIFI_AP_STATE) {
// check RSNIE
if (len > 2 && msg != NULL) {
#ifdef DEBUG_PSK
debug_out("PSK: Rx Assoc-ind, RSNIE", msg, len);
#endif
#ifdef RTL_WPA2
memcpy(tmpbuf, msg, len);
len -= 2;
#else
tmpbuf[0] = RSN_ELEMENT_ID;
tmpbuf[1] = len;
memcpy(tmpbuf+2, msg, len);
#endif
#ifdef RTL_WPA2
isWPA2 = (tmpbuf[0] == WPA2_ELEMENT_ID) ? 1 : 0;
if (isWPA2)
ret = parseIEWPA2(priv, pstat->wpa_sta_info, tmpbuf, len+2);
else
#endif
ret = parseIE(priv, pstat->wpa_sta_info, tmpbuf, len+2);
if (ret != 0) {
DEBUG_ERR("parse IE error [%x]!\n", ret);
}
// issue assoc-rsp successfully
ToDrv_RspAssoc(priv, id, mac, -ret);
if (ret == 0) {
#ifdef EVENT_LOG
char *pmsg;
switch (pstat->wpa_sta_info->UnicastCipher) {
case DOT11_ENC_NONE: pmsg = "none"; break;
case DOT11_ENC_WEP40: pmsg = "WEP40"; break;
case DOT11_ENC_TKIP: pmsg = "TKIP"; break;
case DOT11_ENC_WRAP: pmsg = "AES"; break;
case DOT11_ENC_CCMP: pmsg = "AES"; break;
case DOT11_ENC_WEP104: pmsg = "WEP104"; break;
default: pmsg = "invalid algorithm"; break;
}
#ifdef RTL_WPA2
LOG_MSG("%s-%s PSK authentication in progress...\n", (isWPA2 ? "WPA2" : "WPA"), pmsg);
#else
LOG_MSG("%s-WPA PSK authentication in progress...\n", pmsg);
#endif
#endif
#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC)
LOG_MSG_NOTICE("Authenticating......;note:%02x-%02x-%02x-%02x-%02x-%02x;\n",
pstat->hwaddr[0],
pstat->hwaddr[1],
pstat->hwaddr[2],
pstat->hwaddr[3],
pstat->hwaddr[4],
pstat->hwaddr[5]);
#endif
}
}
else { // RNSIE is null
if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK)
ToDrv_RspAssoc(priv, id, mac, -ERROR_INVALID_RSNIE);
}
}
break;
case DOT11_EVENT_DISASSOCIATION_IND:
reset_sta_info(priv, pstat);
break;
case DOT11_EVENT_MIC_FAILURE:
// do nothing
break;
}
return 0;
}
#endif