summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-13 00:40:35 +0300
committerRoman Yeryomin <roman@advem.lv>2013-05-26 00:44:46 +0300
commita27354c9021a8423ef8c7d2bffad49cbf639eec1 (patch)
tree2355929a4b8cf1888cd0797cfabdb42e0077c524 /target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c
parent24a776baeb5d3cd903b144c89ceb11c5bc36a49e (diff)
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c')
-rw-r--r--target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c3689
1 files changed, 3689 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c b/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c
new file mode 100644
index 000000000..bfa105438
--- /dev/null
+++ b/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_psk.c
@@ -0,0 +1,3689 @@
+/*
+ * WPA PSK handling routines
+ *
+ * $Id: 8192cd_psk.c,v 1.6.2.3 2011/01/07 06:55:01 victoryman 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(INCLUDE_WPA_PSK) && !defined(WIFI_HAPD)) || defined(HAPD_DRV_PSK_WPS)
+
+#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
+
+#ifdef CLIENT_MODE
+#define WAIT_EAP_TIME 500
+#endif
+
+#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);
+
+#define SetNonce(ocDst, oc32Counter) SetEAPOL_KEYIV(ocDst, oc32Counter)
+
+
+#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);
+#ifdef CLIENT_MODE
+extern void AES_UnWRAP(unsigned char *cipher, int cipher_len, unsigned char *kek,
+ int kek_len, unsigned char *plain);
+#endif
+#endif
+
+static void UpdateGK(struct rtl8192cd_priv *priv);
+static void SendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend);
+static void ResendTimeout(unsigned long task_psta);
+
+
+#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");
+
+ }
+}
+
+static char *STATE2RXMSG(struct stat_info *pstat)
+{
+ if (Message_KeyType(pstat->wpa_sta_info->EapolKeyMsgRecvd) == type_Pairwise) {
+ if (pstat->wpa_sta_info->state == PSK_STATE_PTKSTART)
+ return ("4-2");
+ else if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITNEGOTIATING) {
+ if (Message_KeyDataLength(pstat->wpa_sta_info->EapolKeyMsgRecvd) != 0)
+ return ("4-2 (duplicated)");
+ else
+ return ("4-4");
+ }
+ else if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE)
+ return ("4-4 (duplicated)");
+ else
+ return ("invalid state");
+
+ }
+ else
+ return ("2-2");
+
+}
+#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;
+}
+
+static void Message_ReplayCounter_OC2LI(OCTET_STRING f, LARGE_INTEGER * li)
+{
+ li->field.HighPart = ((unsigned long)(*(f.Octet + ReplayCounterPos + 3)))
+ + ((unsigned long)(*(f.Octet + ReplayCounterPos+ 2)) <<8 )
+ + ((unsigned long)(*(f.Octet + ReplayCounterPos + 1)) << 16)
+ + ((unsigned long)(*(f.Octet + ReplayCounterPos + 0)) <<24);
+ li->field.LowPart = ((unsigned long)(*(f.Octet + ReplayCounterPos + 7)))
+ + ((unsigned long)(*(f.Octet + ReplayCounterPos + 6)) <<8 )
+ + ((unsigned long)(*(f.Octet + ReplayCounterPos + 5)) << 16)
+ + ((unsigned long)(*(f.Octet + ReplayCounterPos + 4)) <<24);
+}
+
+#if 1
+/*-----------------------------------------------------------------------------------------------
+ f is EAPOL-KEY message
+ ------------------------------------------------------------------------------------------------*/
+static int Message_EqualReplayCounter(LARGE_INTEGER li1, OCTET_STRING f)
+{
+ LARGE_INTEGER li2;
+ Message_ReplayCounter_OC2LI(f, &li2);
+ if(li1.field.HighPart == li2.field.HighPart && li1.field.LowPart == li2.field.LowPart)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+#ifdef CLIENT_MODE
+/*-------------------------------------------------------------------------------------------
+ li1 is recorded replay counter on STA
+ f is the replay counter from EAPOL-KEY message
+ ---------------------------------------------------------------------------------------------*/
+static int Message_SmallerEqualReplayCounter(LARGE_INTEGER li1, OCTET_STRING f)
+{
+ LARGE_INTEGER li2;
+ Message_ReplayCounter_OC2LI(f, &li2);
+ if(li2.field.HighPart > li1.field.HighPart)
+ return 0;
+ else if(li2.field.HighPart < li1.field.HighPart)
+ return 1;
+ else if(li2.field.LowPart > li1.field.LowPart)
+ return 0;
+ else if(li2.field.LowPart <= li1.field.LowPart)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------------------------
+ li1 is recorded replay counter on STA
+ f is the replay counter from EAPOL-KEY message
+ -----------------------------------------------------------------------------------------------*/
+static int Message_LargerReplayCounter(LARGE_INTEGER li1, OCTET_STRING f)
+{
+ LARGE_INTEGER li2;
+ Message_ReplayCounter_OC2LI(f, &li2);
+
+ if(li2.field.HighPart > li1.field.HighPart)
+ return 1;
+ else if(li2.field.LowPart > li1.field.LowPart)
+ return 1;
+ else
+ return 0;
+}
+
+static void Message_setReplayCounter(OCTET_STRING f, unsigned long h, unsigned long l)
+{
+ LARGE_INTEGER *li = (LARGE_INTEGER *)(f.Octet + ReplayCounterPos);
+ li->charData[0] = (unsigned char)(h >> 24) & 0xff;
+ li->charData[1] = (unsigned char)(h >> 16) & 0xff;
+ li->charData[2] = (unsigned char)(h >> 8) & 0xff;
+ li->charData[3] = (unsigned char)(h >> 0) & 0xff;
+ li->charData[4] = (unsigned char)(l >> 24) & 0xff;
+ li->charData[5] = (unsigned char)(l >> 16) & 0xff;
+ li->charData[6] = (unsigned char)(l >> 8) & 0xff;
+ li->charData[7] = (unsigned char)(l >> 0) & 0xff;
+}
+
+static void 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;
+ 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;
+ 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++;
+ }
+ 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;
+ 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++;
+ }
+ 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;
+ 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
+ ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY);
+ ulIELength += ulRSNCapabilityLength;
+
+ 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);
+
+ 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 void INCLargeInteger(LARGE_INTEGER * x)
+{
+ if (x->field.LowPart == 0xffffffff) {
+ if (x->field.HighPart == 0xffffffff) {
+ x->field.HighPart = 0;
+ x->field.LowPart = 0;
+ }
+ else {
+ x->field.HighPart++;
+ x->field.LowPart = 0;
+ }
+ }
+ else
+ x->field.LowPart++;
+}
+
+static void INCOctet16_INTEGER(OCTET16_INTEGER * x)
+{
+ if (LargeIntegerOverflow(x->field.LowPart)){
+ if (LargeIntegerOverflow(x->field.HighPart)) {
+ LargeIntegerZero(x->field.HighPart);
+ LargeIntegerZero(x->field.LowPart);
+ }
+ else {
+ INCLargeInteger(&x->field.HighPart);
+ LargeIntegerZero(x->field.LowPart);
+ }
+ }
+ else
+ INCLargeInteger(&x->field.LowPart);
+
+}
+
+static OCTET32_INTEGER *INCOctet32_INTEGER(OCTET32_INTEGER * x)
+{
+ if (Octet16IntegerOverflow(x->field.LowPart)) {
+ if (Octet16IntegerOverflow(x->field.HighPart)) {
+ Octet16IntegerZero(x->field.HighPart);
+ Octet16IntegerZero(x->field.LowPart);
+ }
+ else {
+ INCOctet16_INTEGER(&x->field.HighPart);
+ Octet16IntegerZero( x->field.LowPart);
+ }
+ }
+ else
+ INCOctet16_INTEGER(&x->field.LowPart);
+ return x;
+}
+
+static void SetEAPOL_KEYIV(OCTET_STRING ocDst, OCTET32_INTEGER oc32Counter)
+{
+ unsigned char *ptr = ocDst.Octet;
+ unsigned long ulTmp;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.HighPart.field.HighPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.HighPart.field.LowPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.LowPart.field.HighPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.LowPart.field.LowPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+
+ if (ocDst.Length == 16) // for AES
+ return;
+
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.HighPart.field.HighPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.HighPart.field.LowPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.LowPart.field.HighPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+ ptr+=4;
+
+ ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.LowPart.field.LowPart);
+ memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp));
+}
+
+static void EncGTK(struct rtl8192cd_priv *priv, struct stat_info *pstat,
+ unsigned char *kek, int keklen, unsigned char *key,
+ int keylen, unsigned char *out, unsigned short *outlen)
+{
+
+ unsigned char tmp1[257], tmp2[257];
+ RC4_KEY rc4key;
+#ifdef RTL_WPA2
+ unsigned char default_key_iv[] = { 0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6 };
+#endif
+ OCTET_STRING EAPOLMsgSend;
+ lib1x_eapol_key *eapolkey;
+
+ EAPOLMsgSend.Octet = pstat->wpa_sta_info->EAPOLMsgSend.Octet;
+ eapolkey = (lib1x_eapol_key *)(EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+
+ // should refer tx packet, david+2006-04-06
+ // if (Message_KeyDescVer(pstat->wpa_sta_info->EapolKeyMsgRecvd) == key_desc_ver1) {
+ if (Message_KeyDescVer(pstat->wpa_sta_info->EapolKeyMsgSend) == key_desc_ver1) {
+
+ memcpy(tmp1, eapolkey->key_iv, KEY_IV_LEN);
+ memcpy(tmp1 + KEY_IV_LEN, kek, keklen);
+
+ RC4_set_key(&rc4key, KEY_IV_LEN + keklen, tmp1);
+
+ //first 256 bytes are discarded
+ RC4(&rc4key, 256, (unsigned char *)tmp1, (unsigned char *)tmp2);
+ RC4(&rc4key, keylen, (unsigned char *)key, out);
+ *outlen = keylen;
+ }
+#ifdef RTL_WPA2
+ else
+ //according to p75 of 11i/D3.0, the IV should be put in the least significant octecs of
+ //KeyIV field which shall be padded with 0, so eapolkey->key_iv + 8
+ AES_WRAP(key, keylen, default_key_iv, 8, kek, keklen, out, outlen);
+#endif
+}
+
+static int CheckMIC(OCTET_STRING EAPOLMsgRecvd, unsigned char *key, int keylen)
+{
+ int retVal = 0;
+ OCTET_STRING EapolKeyMsgRecvd;
+ unsigned char ucAlgo;
+ OCTET_STRING tmp; //copy of overall 802.1x message
+ unsigned char tmpbuf[512];
+ struct lib1x_eapol *tmpeapol;
+ lib1x_eapol_key *tmpeapolkey;
+ unsigned char sha1digest[20];
+
+ EapolKeyMsgRecvd.Octet = EAPOLMsgRecvd.Octet +
+ ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+ EapolKeyMsgRecvd.Length = EAPOLMsgRecvd.Length -
+ (ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+ ucAlgo = Message_KeyDescVer(EapolKeyMsgRecvd);
+
+ tmp.Length = EAPOLMsgRecvd.Length;
+ tmp.Octet = tmpbuf;
+ memcpy(tmp.Octet, EAPOLMsgRecvd.Octet, EAPOLMsgRecvd.Length);
+ tmpeapol = (struct lib1x_eapol *)(tmp.Octet + ETHER_HDRLEN);
+ tmpeapolkey = (lib1x_eapol_key *)(tmp.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+ memset(tmpeapolkey->key_mic, 0, KEY_MIC_LEN);
+
+ if (ucAlgo == key_desc_ver1) {
+ hmac_md5((unsigned char*)tmpeapol, EAPOLMsgRecvd.Length - ETHER_HDRLEN ,
+ key, keylen, tmpeapolkey->key_mic);
+#if 0
+ lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "CheckMIC", EapolKeyMsgRecvd.Octet +
+ KeyMICPos, KEY_MIC_LEN, "Original");
+ lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "CheckMIC", tmpeapolkey->key_mic,
+ KEY_MIC_LEN, "Calculated");
+#endif
+ if (!memcmp(tmpeapolkey->key_mic, EapolKeyMsgRecvd.Octet + KeyMICPos, KEY_MIC_LEN))
+ retVal = 1;
+ }
+ else if (ucAlgo == key_desc_ver2) {
+ hmac_sha1((unsigned char*)tmpeapol, EAPOLMsgRecvd.Length - ETHER_HDRLEN , key, keylen, sha1digest);
+ if (!memcmp(sha1digest, EapolKeyMsgRecvd.Octet + KeyMICPos, KEY_MIC_LEN))
+ retVal = 1;
+ }
+ return retVal;
+}
+
+static void CalcMIC(OCTET_STRING EAPOLMsgSend, int algo, unsigned char *key, int keylen)
+{
+ struct lib1x_eapol *eapol = (struct lib1x_eapol *)(EAPOLMsgSend.Octet+ETHER_HDRLEN);
+ lib1x_eapol_key *eapolkey = (lib1x_eapol_key *)(EAPOLMsgSend.Octet+ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+ unsigned char sha1digest[20];
+
+ memset(eapolkey->key_mic, 0, KEY_MIC_LEN);
+
+ if (algo == key_desc_ver1)
+ hmac_md5((unsigned char*)eapol, EAPOLMsgSend.Length - ETHER_HDRLEN ,
+ key, keylen, eapolkey->key_mic);
+ else if (algo == key_desc_ver2) {
+ hmac_sha1((unsigned char*)eapol, EAPOLMsgSend.Length - ETHER_HDRLEN ,
+ key, keylen, sha1digest);
+ memcpy(eapolkey->key_mic, sha1digest, KEY_MIC_LEN);
+ }
+}
+
+/* GTK-PRF-X
+ X = 256 in TKIP
+ X = 128 in CCMP, WRAP, and WEP
+ */
+static void CalcGTK(unsigned char *addr, unsigned char *nonce,
+ unsigned char *keyin, int keyinlen,
+ unsigned char *keyout, int keyoutlen)
+{
+ unsigned char data[ETHER_ADDRLEN + KEY_NONCE_LEN], tmp[64];
+
+ memcpy(data, addr, ETHER_ADDRLEN);
+ memcpy(data + ETHER_ADDRLEN, nonce, KEY_NONCE_LEN);
+
+ i_PRF(keyin, keyinlen, (unsigned char*)GMK_EXPANSION_CONST,
+ GMK_EXPANSION_CONST_SIZE, data, sizeof(data),
+ tmp, keyoutlen);
+ memcpy(keyout, tmp, keyoutlen);
+}
+
+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 void CalcPTK(unsigned char *addr1, unsigned char *addr2,
+ unsigned char *nonce1, unsigned char *nonce2,
+ unsigned char * keyin, int keyinlen,
+ unsigned char *keyout, int keyoutlen)
+{
+ unsigned char data[2*ETHER_ADDRLEN+ 2*KEY_NONCE_LEN], tmpPTK[128];
+
+ if(MIN(addr1, addr2, ETHER_ADDRLEN)<=0)
+ {
+ memcpy(data, addr1, ETHER_ADDRLEN);
+ memcpy(data + ETHER_ADDRLEN, addr2, ETHER_ADDRLEN);
+ }else
+ {
+ memcpy(data, addr2, ETHER_ADDRLEN);
+ memcpy(data + ETHER_ADDRLEN, addr1, ETHER_ADDRLEN);
+ }
+ if(MIN(nonce1, nonce2, KEY_NONCE_LEN)<=0)
+ {
+ memcpy(data + 2*ETHER_ADDRLEN, nonce1, KEY_NONCE_LEN);
+ memcpy(data + 2*ETHER_ADDRLEN + KEY_NONCE_LEN, nonce2, KEY_NONCE_LEN);
+ }else
+ {
+ memcpy(data + 2*ETHER_ADDRLEN, nonce2, KEY_NONCE_LEN);
+ memcpy(data + 2*ETHER_ADDRLEN + KEY_NONCE_LEN, nonce1, KEY_NONCE_LEN);
+ }
+
+ i_PRF(keyin, keyinlen, (unsigned char*)PMK_EXPANSION_CONST,
+ PMK_EXPANSION_CONST_SIZE, data,sizeof(data),
+ tmpPTK, PTK_LEN_TKIP);
+ memcpy(keyout, tmpPTK, keyoutlen);
+}
+
+#ifdef CLIENT_MODE
+/*
+ decrypt WPA2 Message 3's Key Data
+ */
+// Use RC4 or AES to decode the keydata by checking desc-ver, david-2006-01-06
+//int DecWPA2KeyData(u_char *key, int keylen, u_char *kek, int keklen, u_char *kout)
+int DecWPA2KeyData(WPA_STA_INFO* pStaInfo, unsigned char *key, int keylen, unsigned char *kek, int keklen, unsigned char *kout)
+{
+ int retVal = 0;
+ unsigned char default_key_iv[] = { 0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6 };
+ unsigned char tmp2[257];
+
+ // Use RC4 or AES to decode the keydata by checking desc-ver, david-2006-01-06
+ unsigned char tmp1[257];
+ RC4_KEY rc4key;
+
+ lib1x_eapol_key *eapolkey = (lib1x_eapol_key *)(pStaInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+
+ if (Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd) == key_desc_ver1) {
+ memcpy(tmp1, eapolkey->key_iv, KEY_IV_LEN);
+ memcpy(tmp1+KEY_IV_LEN, kek, keklen);
+ RC4_set_key(&rc4key, KEY_IV_LEN + keklen, tmp1);
+
+ //first 256 bits is discard
+ RC4(&rc4key, 256, (unsigned char*)tmp1, (unsigned char*)tmp2);
+
+ //RC4(&rc4key, keylen, eapol_key->key_data, global->skm_sm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)]);
+ RC4(&rc4key, keylen, pStaInfo->EapolKeyMsgRecvd.Octet + KeyDataPos, (unsigned char*)tmp2);
+
+ memcpy(kout, tmp2, keylen);
+ //memcpy(&global->supp_kmsm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)], tmp2, keylen);
+ retVal = 1;
+ }
+ else {
+ //--------------------------------------------------------
+ AES_UnWRAP(key, keylen, kek, keklen, tmp2);
+ if(memcmp(tmp2, default_key_iv, 8))
+ retVal = 0;
+ else {
+ memcpy(kout, tmp2+8, keylen);
+ retVal = 1;
+ }
+ }
+ return retVal;
+}
+
+int DecGTK(OCTET_STRING EAPOLMsgRecvd, unsigned char *kek, int keklen, int keylen, unsigned char *kout)
+{
+ int retVal = 0;
+ unsigned char tmp1[257], tmp2[257];
+ RC4_KEY rc4key;
+ lib1x_eapol_key * eapol_key = (lib1x_eapol_key *)(EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+ OCTET_STRING EapolKeyMsgRecvd;
+ EapolKeyMsgRecvd.Octet = EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+ EapolKeyMsgRecvd.Length = EAPOLMsgRecvd.Length - (ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN);
+
+ if(Message_KeyDescVer(EapolKeyMsgRecvd) == key_desc_ver1)
+ {
+ memcpy(tmp1, eapol_key->key_iv, KEY_IV_LEN);
+ memcpy(tmp1 + KEY_IV_LEN, kek, keklen);
+ RC4_set_key(&rc4key, KEY_IV_LEN + keklen, tmp1);
+ //first 256 bits is discard
+ RC4(&rc4key, 256, (unsigned char*)tmp1, (unsigned char*)tmp2);
+ //RC4(&rc4key, keylen, eapol_key->key_data, global->skm_sm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)]);
+ RC4(&rc4key, keylen, EapolKeyMsgRecvd.Octet + KeyDataPos, (unsigned char*)tmp2);
+ memcpy(kout, tmp2, keylen);
+ //memcpy(&global->supp_kmsm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)], tmp2, keylen);
+ retVal = 1;
+ }
+ else if(Message_KeyDescVer(EapolKeyMsgRecvd) == key_desc_ver2)
+ {
+ // kenny: should use default IV 0xA6A6A6A6A6A6A6A6
+ unsigned char default_key_iv[] = { 0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6 };
+ // david, get key len from eapol packet
+ // AES_UnWRAP(EapolKeyMsgRecvd.Octet + KeyDataPos, keylen + 8, kek, keklen, tmp2);
+
+ keylen = Message_KeyDataLength(EapolKeyMsgRecvd);
+ AES_UnWRAP(EapolKeyMsgRecvd.Octet + KeyDataPos, keylen, kek, keklen, tmp2);
+ //------------------------- 2005-08-01
+
+ //if(memcmp(tmp2, eapol_key->key_iv + 8, 8))
+ if(memcmp(tmp2, default_key_iv, 8))
+ retVal = 0;
+ else
+ {
+ //memcpy(kout, tmp2, keylen);
+ //memcpy(global->supp_kmsm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)], tmp2 + 8, keylen - 8);
+ memcpy(kout, tmp2+8, keylen);
+ retVal = 1;
+ }
+ }
+ return retVal;
+}
+#endif /* CLIENT_MODE */
+
+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;
+
+ 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;
+ }
+
+ 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
+
+ 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 */
+
+ 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;
+ }
+
+ if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) {
+ 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;
+ }
+
+ 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;
+ 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 ||
+ pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK) {
+ DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 11!\n");
+ return ERROR_INVALID_AUTHKEYMANAGE;
+ }
+
+ if(pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK) {
+ 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
+ pucIE += 2;
+
+ // 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;
+ /*
+ 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;
+ }
+ }
+
+ }
+ */
+ return 0;
+}
+#endif // RTL_WPA2
+
+static void GenNonce(unsigned char *nonce, unsigned char *addr)
+{
+ unsigned char secret[256], random[256], result[256];
+
+ get_random_bytes(random, 256);
+ memset(secret, 0, sizeof(secret));
+
+ i_PRF(secret, sizeof(secret), (unsigned char*)RANDOM_EXPANSION_CONST, RANDOM_EXPANSION_CONST_SIZE,
+ random, sizeof(random), result, KEY_NONCE_LEN);
+
+ memcpy(nonce, result, KEY_NONCE_LEN);
+}
+
+static void IntegrityFailure(struct rtl8192cd_priv *priv)
+{
+ priv->wpa_global_info->IntegrityFailed = FALSE;
+
+ if (priv->wpa_global_info->GKeyFailure) {
+ priv->wpa_global_info->GTKRekey = TRUE;
+ priv->wpa_global_info->GKeyFailure = FALSE;
+ }
+
+ //waitupto60;
+ INCOctet32_INTEGER(&priv->wpa_global_info->Counter);
+ // SetNonce(global->akm_sm->ANonce, global->auth->Counter);
+
+ INCOctet32_INTEGER(&priv->wpa_global_info->Counter);
+ // SetNonce(global->akm_sm->ANonce, global->auth->Counter);
+}
+
+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_SetPTK(struct rtl8192cd_priv *priv, struct stat_info *pstat)
+{
+ unsigned long ulKeyLength = 0;
+ unsigned char *pucKeyMaterial = 0;
+ struct iw_point wrq;
+ DOT11_SET_KEY Set_Key;
+
+#ifdef DEBUG_PSK
+ printk("PSK: Set PTK, mac: %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
+
+ wrq.pointer = (caddr_t)&Set_Key;
+ Set_Key.EventId = DOT11_EVENT_SET_KEY;
+ Set_Key.IsMoreEvent = FALSE;
+ Set_Key.KeyIndex = 0;
+ Set_Key.KeyType = DOT11_KeyType_Pairwise;
+ memcpy(&Set_Key.MACAddr, pstat->hwaddr, 6);
+ switch (pstat->wpa_sta_info->UnicastCipher) {
+ case DOT11_ENC_TKIP:
+ ulKeyLength = PTK_LEN_TKIP - (PTK_LEN_EAPOLMIC + PTK_LEN_EAPOLENC);
+ break;
+
+ // Kenny
+ case DOT11_ENC_CCMP:
+ ulKeyLength = PTK_LEN_CCMP - (PTK_LEN_EAPOLMIC + PTK_LEN_EAPOLENC);
+ break;
+ }
+ pucKeyMaterial = pstat->wpa_sta_info->PTK + (PTK_LEN_EAPOLMIC + PTK_LEN_EAPOLENC);
+
+ //sc_yang
+ memset(Set_Key.KeyMaterial,0, 64);
+ memcpy(Set_Key.KeyMaterial, pucKeyMaterial, ulKeyLength);
+ Set_Key.EncType = pstat->wpa_sta_info->UnicastCipher;
+ Set_Key.KeyLen = ulKeyLength;
+ wrq.length = sizeof(DOT11_SET_KEY) - 1 + ulKeyLength;
+
+#ifdef DEBUG_PSK
+ debug_out(NULL, Set_Key.KeyMaterial, ulKeyLength);
+#endif
+
+ rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq);
+}
+
+void ToDrv_SetGTK(struct rtl8192cd_priv *priv)
+{
+ unsigned long ulKeyLength = 0;
+ //unsigned long ulKeyIndex = 0;
+ struct iw_point wrq;
+ DOT11_SET_KEY Set_Key;
+ unsigned char szBradcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+#ifdef DEBUG_PSK
+ printk("PSK: Set GTK\n");
+#endif
+
+ wrq.pointer = (caddr_t)&Set_Key;
+ wrq.length = sizeof(DOT11_SET_KEY);
+
+ Set_Key.EventId = DOT11_EVENT_SET_KEY;
+ Set_Key.IsMoreEvent = FALSE;
+
+ Set_Key.KeyType = DOT11_KeyType_Group;
+ memcpy(&Set_Key.MACAddr, szBradcast, 6);
+
+ Set_Key.EncType = priv->wpa_global_info->MulticastCipher;
+ //sc_yang
+ memset(Set_Key.KeyMaterial,0, 64);
+ ulKeyLength = 32;
+#ifdef CLIENT_MODE
+ if (OPMODE & WIFI_ADHOC_STATE)
+ {
+ memcpy(Set_Key.KeyMaterial, priv->wpa_global_info->PSK, ulKeyLength);
+ Set_Key.KeyIndex = 0;
+ }
+ else
+#endif
+ {
+ //ulKeyIndex = priv->wpa_global_info->GN;
+ memcpy(Set_Key.KeyMaterial,
+ priv->wpa_global_info->GTK[priv->wpa_global_info->GN],
+ ulKeyLength);
+ Set_Key.KeyIndex = priv->wpa_global_info->GN;
+ }
+
+ wrq.length = sizeof(DOT11_SET_KEY) - 1 + ulKeyLength;
+ wrq.length = sizeof(DOT11_SET_KEY) - 1 + ulKeyLength;
+
+#ifdef DEBUG_PSK
+ debug_out(NULL, Set_Key.KeyMaterial, ulKeyLength);
+#endif
+
+ 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 ToDrv_DisconnectSTA(struct rtl8192cd_priv *priv, struct stat_info *pstat, int reason)
+{
+ struct iw_point wrq;
+ DOT11_DISCONNECT_REQ Disconnect_Req;
+
+#ifdef DEBUG_PSK
+ printk("PSK: disconnect sta, mac: %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
+
+ wrq.pointer = (caddr_t)&Disconnect_Req;
+ wrq.length = sizeof(DOT11_DISCONNECT_REQ);
+
+ Disconnect_Req.EventId = DOT11_EVENT_DISCONNECT_REQ;
+ Disconnect_Req.IsMoreEvent = FALSE;
+ Disconnect_Req.Reason = (unsigned short)reason;
+ memcpy(Disconnect_Req.MACAddr, pstat->hwaddr, 6);
+
+ rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq);
+};
+
+static void ToDrv_IndicateMICFail(struct rtl8192cd_priv *priv, unsigned char *mac)
+{
+ struct iw_point wrq;
+ DOT11_MIC_FAILURE MIC_Failure;
+
+ wrq.pointer = (caddr_t)&MIC_Failure;
+ wrq.length = sizeof(DOT11_INIT_QUEUE);
+
+ MIC_Failure.EventId = DOT11_EVENT_MIC_FAILURE;
+ memcpy(MIC_Failure.MACAddr, mac, 6);
+
+ 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;
+
+ unsigned long flags;
+
+ SAVE_INT_AND_CLI(flags);
+
+ if (timer_pending(&pInfo->resendTimer))
+ del_timer_sync(&pInfo->resendTimer);
+
+ 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->ANonce.Octet = pInfo->AnonceBuf;
+ pInfo->ANonce.Length = KEY_NONCE_LEN;
+
+ pInfo->SNonce.Octet = pInfo->SnonceBuf;
+ pInfo->SNonce.Length = KEY_NONCE_LEN;
+
+ pInfo->EAPOLMsgSend.Octet = pInfo->eapSendBuf;
+ pInfo->EapolKeyMsgSend.Octet = pInfo->EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+
+ pInfo->EAPOLMsgRecvd.Octet = pInfo->eapRecvdBuf;
+ pInfo->EapolKeyMsgRecvd.Octet = pInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+
+ init_timer(&pInfo->resendTimer);
+ pInfo->resendTimer.data = (unsigned long)pstat;
+ pInfo->resendTimer.function = ResendTimeout;
+ pInfo->priv = priv;
+
+ if (OPMODE & WIFI_AP_STATE)
+ {
+ pInfo->state = PSK_STATE_IDLE;
+ }
+#ifdef CLIENT_MODE
+ else if (OPMODE & WIFI_STATION_STATE)
+ {
+ memcpy(pInfo->PMK, priv->wpa_global_info->PSK, PMK_LEN);
+
+ pInfo->clientHndshkProcessing = FALSE;
+ pInfo->clientHndshkDone = FALSE;
+
+ pInfo->CurrentReplayCounter.field.HighPart = 0xffffffff;
+ pInfo->CurrentReplayCounter.field.LowPart = 0xffffffff;
+ }
+#endif
+
+ RESTORE_INT(flags);
+}
+
+static void ResendTimeout(unsigned long task_psta)
+{
+ struct stat_info *pstat = (struct stat_info *)task_psta;
+ struct rtl8192cd_priv *priv = pstat->wpa_sta_info->priv;
+
+ DEBUG_TRACE;
+
+ if (!(priv->drv_state & DRV_STATE_OPEN))
+ return;
+
+ if (pstat == NULL)
+ return;
+
+#ifdef CLIENT_MODE
+ if ((OPMODE & WIFI_STATION_STATE) && !pstat->wpa_sta_info->clientHndshkProcessing) {
+ DEBUG_ERR("Wait EAP timeout, disconnect AP!\n");
+ ToDrv_DisconnectSTA(priv, pstat, expire);
+ return;
+ }
+#endif
+
+ if (++pstat->wpa_sta_info->resendCnt > MAX_RESEND_NUM) {
+
+ // When the case of group rekey timeout, update GTK to driver when it is
+ // the last one node
+ if (OPMODE & WIFI_AP_STATE) {
+ if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE &&
+ pstat->wpa_sta_info->gstate == PSK_GSTATE_REKEYNEGOTIATING) {
+ if (priv->wpa_global_info->GKeyDoneStations > 0)
+ priv->wpa_global_info->GKeyDoneStations--;
+
+ if (priv->wpa_global_info->GKeyDoneStations==0 && !priv->wpa_global_info->GkeyReady) {
+ ToDrv_SetGTK(priv);
+ priv->wpa_global_info->GkeyReady = TRUE;
+ priv->wpa_global_info->GResetCounter = TRUE;
+
+ // start groupkey rekey timer
+ if (priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime)
+ mod_timer(&priv->wpa_global_info->GKRekeyTimer, jiffies + RTL_SECONDS_TO_JIFFIES(priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime));
+
+ // if only one sta and group key rekey fail, don't disconnect the sta
+ if (get_assoc_sta_num(priv) == 1) {
+#ifdef DEBUG_PSK
+ printk("!!!!DO NOT disconnect STA under 1 client case!!!\n");
+#endif
+ return;
+ }
+
+ }
+ }
+ }
+ //--------------------------------------------------------- david+2006-04-06
+
+ ToDrv_DisconnectSTA(priv, pstat, RSN_4_way_handshake_timeout);
+ // need not reset because ToDrv_DisconnectSTA() will take care of it, david+2006-04-06
+ // reset_sta_info(priv, pstat);
+
+#ifdef DEBUG_PSK
+ printk("PSK: Exceed max retry, disconnect sta\n");
+#endif
+ }
+ else
+ {
+ if (OPMODE & WIFI_AP_STATE)
+ SendEAPOL(priv, pstat, 1);
+#ifdef CLIENT_MODE
+ else if (OPMODE & WIFI_STATION_STATE)
+ ClientSendEAPOL(priv, pstat, 1);
+#endif
+ }
+}
+
+static void GKRekeyTimeout(unsigned long task_priv)
+{
+ struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv;
+ unsigned long flags;
+
+ DEBUG_TRACE;
+
+ if (!(priv->drv_state & DRV_STATE_OPEN))
+ return;
+
+ SAVE_INT_AND_CLI(flags);
+ SMP_LOCK(flags);
+
+ priv->wpa_global_info->GTKRekey = TRUE;
+ UpdateGK(priv);
+
+ RESTORE_INT(flags);
+ SMP_UNLOCK(flags);
+}
+
+static void SendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend)
+{
+ OCTET_STRING IV, RSC, KeyID, MIC, KeyData, EAPOLMsgSend, EapolKeyMsgSend;
+ unsigned char IV_buff[KEY_IV_LEN], RSC_buff[KEY_RSC_LEN];
+ unsigned char ID_buff[KEY_ID_LEN], MIC_buff[KEY_MIC_LEN], KEY_buff[INFO_ELEMENT_SIZE];
+ unsigned short tmpKeyData_Length;
+ unsigned char KeyDescriptorVer=key_desc_ver1;
+ int IfCalcMIC = 0;
+ struct wlan_ethhdr_t *eth_hdr;
+ struct lib1x_eapol *eapol;
+ struct sk_buff *pskb;
+ lib1x_eapol_key *eapol_key;
+ WPA_STA_INFO *pStaInfo;
+ WPA_GLOBAL_INFO *pGblInfo;
+
+ DEBUG_TRACE;
+
+ if (priv == NULL || pstat == NULL)
+ return;
+
+ pStaInfo = pstat->wpa_sta_info;
+ pGblInfo = priv->wpa_global_info;
+
+ if (pStaInfo->state == PSK_STATE_IDLE)
+ return;
+
+ memset(&EapolKeyMsgSend, 0, sizeof(EapolKeyMsgSend));
+ EAPOLMsgSend.Octet = pStaInfo->EAPOLMsgSend.Octet;
+ EapolKeyMsgSend.Octet = EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+ pStaInfo->EapolKeyMsgSend.Octet = EapolKeyMsgSend.Octet;
+ eapol_key = (lib1x_eapol_key *)EapolKeyMsgSend.Octet;
+
+ if ((pGblInfo->MulticastCipher == _CCMP_PRIVACY_) || (pStaInfo->UnicastCipher == _CCMP_PRIVACY_))
+ KeyDescriptorVer = key_desc_ver2;
+
+ if (resend) {
+ EAPOLMsgSend.Length = pStaInfo->EAPOLMsgSend.Length;
+ EapolKeyMsgSend.Length = pStaInfo->EapolKeyMsgSend.Length;
+ Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart);
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+ IfCalcMIC = TRUE;
+ goto send_packet;
+ }
+
+ IV.Octet = IV_buff;
+ IV.Length = KEY_IV_LEN;
+ RSC.Octet = RSC_buff;
+ RSC.Length = KEY_RSC_LEN;
+ KeyID.Octet = ID_buff;
+ KeyID.Length = KEY_ID_LEN;
+ MIC.Octet = MIC_buff;
+ MIC.Length = KEY_MIC_LEN;
+ KeyData.Octet = KEY_buff;
+ KeyData.Length = 0;
+
+ switch(pStaInfo->state) {
+ case PSK_STATE_PTKSTART:
+ //send 1st message of 4-way handshake
+ DEBUG_INFO("4-1\n");
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2)
+ Message_setDescType(EapolKeyMsgSend, desc_type_WPA2);
+ else
+#endif
+ Message_setDescType(EapolKeyMsgSend, desc_type_RSN);
+
+ Message_setKeyDescVer(EapolKeyMsgSend, KeyDescriptorVer);
+ Message_setKeyType(EapolKeyMsgSend, type_Pairwise);
+ Message_setKeyIndex(EapolKeyMsgSend, 0);
+ Message_setInstall(EapolKeyMsgSend, 0);
+ Message_setKeyAck(EapolKeyMsgSend, 1);
+ Message_setKeyMIC(EapolKeyMsgSend, 0);
+ Message_setSecure(EapolKeyMsgSend, 0);
+ Message_setError(EapolKeyMsgSend, 0);
+ Message_setRequest(EapolKeyMsgSend, 0);
+ Message_setReserved(EapolKeyMsgSend, 0);
+ Message_setKeyLength(EapolKeyMsgSend, (pStaInfo->UnicastCipher == DOT11_ENC_TKIP) ? 32:16);
+ // Message_setKeyLength(EapolKeyMsgSend, 32);
+
+ // make 4-1's ReplyCounter increased
+ Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart);
+ memcpy(&pStaInfo->ReplayCounterStarted, &pStaInfo->CurrentReplayCounter, sizeof(LARGE_INTEGER)); // save started reply counter, david+1-12-2007
+
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+
+ INCOctet32_INTEGER(&pGblInfo->Counter);
+ //#ifndef RTL_WPA2_PREAUTH
+ // ANonce is only updated in lib1x_init_authenticator()
+ // or after 4-way handshake
+ // To avoid different ANonce values among multiple issued 4-1 messages because of multiple association requests
+ // Different ANonce values among multiple 4-1 messages induce 4-2 MIC failure.
+ SetNonce(pStaInfo->ANonce, pGblInfo->Counter);
+ //#endif
+ Message_setKeyNonce(EapolKeyMsgSend, pStaInfo->ANonce);
+
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+
+ // enable it to interoper with Intel 11n Centrino, david+2007-11-19
+#if 1
+ // otherwise PMK cache
+ if ((pStaInfo->RSNEnabled & PSK_WPA2) && (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK || pStaInfo->PMKCached) ) {
+ static char PMKID_KDE_TYPE[] = { 0xDD, 0x14, 0x00, 0x0F, 0xAC, 0x04 };
+ Message_setKeyDataLength(EapolKeyMsgSend, 22);
+ memcpy(EapolKeyMsgSend.Octet + KeyDataPos,
+ PMKID_KDE_TYPE, sizeof(PMKID_KDE_TYPE));
+ // memcpy(EapolKeyMsgSend.Octet+KeyDataPos+sizeof(PMKID_KDE_TYPE),
+ // global->akm_sm->PMKID, PMKID_LEN);
+ }
+ else
+#endif
+ Message_setKeyDataLength(EapolKeyMsgSend, 0);
+
+ memset(MIC.Octet, 0, MIC.Length);
+ Message_setMIC(EapolKeyMsgSend, MIC);
+
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2)
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + Message_KeyDataLength(EapolKeyMsgSend);
+ else
+#endif
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN;
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+ break;
+
+ case PSK_STATE_PTKINITNEGOTIATING:
+
+ //Construct Message3
+ DEBUG_INFO("4-3\n");
+
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2)
+ Message_setDescType(EapolKeyMsgSend, desc_type_WPA2);
+ else
+#endif
+ Message_setDescType(EapolKeyMsgSend, desc_type_RSN);
+
+ Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyIndex(EapolKeyMsgSend, Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd));
+
+ //Message_setInstall(global->EapolKeyMsgSend, global->RSNVariable.isSuppSupportUnicastCipher ? 1:0);
+ Message_setInstall(EapolKeyMsgSend, 1);
+ Message_setKeyAck(EapolKeyMsgSend, 1);
+ Message_setKeyMIC(EapolKeyMsgSend, 1);
+ //??
+ // Message_setSecure(pStaInfo->EapolKeyMsgSend, pStaInfo->RSNVariable.isSuppSupportMulticastCipher ? 0:1);
+ Message_setSecure(EapolKeyMsgSend, 0);
+ //??
+ Message_setError(EapolKeyMsgSend, 0);
+ Message_setRequest(EapolKeyMsgSend, 0);
+ Message_setReserved(EapolKeyMsgSend, 0);
+ Message_setKeyLength(EapolKeyMsgSend, (pStaInfo->UnicastCipher == DOT11_ENC_TKIP) ? 32:16);
+ Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart);
+ Message_setKeyNonce(EapolKeyMsgSend, pStaInfo->ANonce);
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2) {
+ unsigned char key_data[128];
+ unsigned char *key_data_pos = key_data;
+ int i;
+ unsigned char GTK_KDE_TYPE[] = {0xDD, 0x16, 0x00, 0x0F, 0xAC, 0x01, 0x01, 0x00 };
+
+ EapolKeyMsgSend.Octet[1] = 0x13;
+ //???
+ if (KeyDescriptorVer == key_desc_ver2 ) {
+ INCOctet32_INTEGER(&pGblInfo->Counter);
+ SetEAPOL_KEYIV(IV, pGblInfo->Counter);
+ //memset(IV.Octet, 0x0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+ }
+ // RSN IE
+ if (pGblInfo->AuthInfoElement.Octet[0] == WPA2_ELEMENT_ID) {
+ int len = (unsigned char)pGblInfo->AuthInfoElement.Octet[1] + 2;
+ if (len > 100) {
+ DEBUG_ERR("invalid IE length!\n");
+ return;
+ }
+ memcpy(key_data_pos, pGblInfo->AuthInfoElement.Octet, len);
+ key_data_pos += len;
+ } else {
+ //find WPA2_ELEMENT_ID 0x30
+ int len = (unsigned char)pGblInfo->AuthInfoElement.Octet[1] + 2;
+ //printf("%s: global->auth->RSNVariable.AuthInfoElement.Octet[%d] = %02X\n", (char *)__FUNCTION__, len, global->auth->RSNVariable.AuthInfoElement.Octet[len]);
+ if (pGblInfo->AuthInfoElement.Octet[len] == WPA2_ELEMENT_ID) {
+ int len2 = (unsigned char)pGblInfo->AuthInfoElement.Octet[len+1] + 2;
+ memcpy(key_data_pos, pGblInfo->AuthInfoElement.Octet+len, len2);
+ key_data_pos += len2;
+ } else {
+ DEBUG_ERR("%d ERROR!\n", __LINE__);
+ }
+ }
+
+ memcpy(key_data_pos, GTK_KDE_TYPE, sizeof(GTK_KDE_TYPE));
+ key_data_pos[1] = (unsigned char) 6 + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16);
+ key_data_pos += sizeof(GTK_KDE_TYPE);
+
+
+ // FIX GROUPKEY ALL ZERO
+ // david+2006-04-04, fix the issue of re-generating group key
+ // pGblInfo->GInitAKeys = TRUE;
+ UpdateGK(priv);
+ memcpy(key_data_pos, pGblInfo->GTK[pGblInfo->GN], (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16);
+
+ key_data_pos += (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16;
+ i = (key_data_pos - key_data) % 8;
+ if ( i != 0 ) {
+ *key_data_pos = 0xdd;
+ key_data_pos++;
+ for (i=i+1; i<8; i++) {
+ *key_data_pos = 0x0;
+ key_data_pos++;
+ }
+
+ }
+ EncGTK(priv, pstat,
+ pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC,
+ key_data,
+ (key_data_pos - key_data),
+ KeyData.Octet, &tmpKeyData_Length);
+ KeyData.Length = (int)tmpKeyData_Length;
+ Message_setKeyData(EapolKeyMsgSend, KeyData);
+ Message_setKeyDataLength(EapolKeyMsgSend, KeyData.Length);
+
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + KeyData.Length;
+ RSC.Octet[0] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0;
+ RSC.Octet[1] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1;
+ RSC.Octet[2] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2;
+ RSC.Octet[3] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3;
+ RSC.Octet[4] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4;
+ RSC.Octet[5] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5;
+ RSC.Octet[6] = 0;
+ RSC.Octet[7] = 0;
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ }
+ else
+#endif // RTL_WPA2
+ { // WPA
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+ //lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "lib1x_akmsm_ProcessEAPOL_proc", global->auth->RSNVariable.AuthInfoElement.Octet, global->auth->RSNVariable.AuthInfoElement.Length,"Append Authenticator Information Element");
+
+ { //WPA 0xDD
+ //printf("%s: global->auth->RSNVariable.AuthInfoElement.Octet[0] = %02X\n", (char *)__FUNCTION__, global->auth->RSNVariable.AuthInfoElement.Octet[0]);
+
+ int len = (unsigned char)pGblInfo->AuthInfoElement.Octet[1] + 2;
+
+ if (pGblInfo->AuthInfoElement.Octet[0] == RSN_ELEMENT_ID) {
+ memcpy(KeyData.Octet, pGblInfo->AuthInfoElement.Octet, len);
+ KeyData.Length = len;
+ } else {
+ // impossible case??
+ int len2 = (unsigned char)pGblInfo->AuthInfoElement.Octet[len+1] + 2;
+ memcpy(KeyData.Octet, pGblInfo->AuthInfoElement.Octet+len, len2);
+ KeyData.Length = len2;
+ }
+ }
+ Message_setKeyDataLength(EapolKeyMsgSend, KeyData.Length);
+ Message_setKeyData(EapolKeyMsgSend, KeyData);
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + KeyData.Length;
+ }
+
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+
+#if 0
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+ //lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "lib1x_akmsm_ProcessEAPOL_proc", global->auth->RSNVariable.AuthInfoElement.Octet, global->auth->RSNVariable.AuthInfoElement.Length,"Append Authenticator Information Element");
+ Message_setKeyDataLength(EapolKeyMsgSend, pGblInfo->AuthInfoElement.Length);
+ Message_setKeyData(EapolKeyMsgSend, pGblInfo->AuthInfoElement);
+ //Message_setKeyDataLength(global->EapolKeyMsgSend, global->akm_sm->AuthInfoElement.Length);
+ //Message_setKeyData(global->EapolKeyMsgSend, global->akm_sm->AuthInfoElement);
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + pGblInfo->AuthInfoElement.Length;
+#endif /* RTL_WPA2 */
+
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+ IfCalcMIC = TRUE;
+ break;
+
+ case PSK_STATE_PTKINITDONE:
+ //send 1st message of 2-way handshake
+ DEBUG_INFO("2-1\n");
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2)
+ Message_setDescType(EapolKeyMsgSend, desc_type_WPA2);
+ else
+#endif
+ Message_setDescType(EapolKeyMsgSend, desc_type_RSN);
+
+ Message_setKeyDescVer(EapolKeyMsgSend, KeyDescriptorVer);
+ Message_setKeyType(EapolKeyMsgSend, type_Group);
+ Message_setKeyIndex(EapolKeyMsgSend, 1);
+ Message_setInstall(EapolKeyMsgSend, 1);
+ Message_setKeyAck(EapolKeyMsgSend, 1);
+ Message_setKeyMIC(EapolKeyMsgSend, 1);
+ Message_setSecure(EapolKeyMsgSend, 1);
+ Message_setError(EapolKeyMsgSend, 0);
+ Message_setRequest(EapolKeyMsgSend, 0);
+ Message_setReserved(EapolKeyMsgSend, 0);
+
+ EapolKeyMsgSend.Octet[1] = 0x03;
+ if (KeyDescriptorVer == key_desc_ver1 )
+ EapolKeyMsgSend.Octet[2] = 0x91;
+ else
+ EapolKeyMsgSend.Octet[2] = 0x92;
+
+ Message_setKeyLength(EapolKeyMsgSend, (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16);
+ Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart);
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+ // kenny: n+2
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+ SetNonce(pGblInfo->GNonce, pGblInfo->Counter);
+ Message_setKeyNonce(EapolKeyMsgSend, pGblInfo->GNonce);
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+
+ RSC.Octet[0] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0;
+ RSC.Octet[1] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1;
+ RSC.Octet[2] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2;
+ RSC.Octet[3] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3;
+ RSC.Octet[4] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4;
+ RSC.Octet[5] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5;
+ RSC.Octet[6] = 0;
+ RSC.Octet[7] = 0;
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2) {
+ char key_data[128];
+ char *key_data_pos = key_data;
+ static char GTK_KDE_TYPE[] = { 0xDD, 0x16, 0x00, 0x0F, 0xAC, 0x01, 0x01, 0x00 };
+ memcpy(key_data_pos, GTK_KDE_TYPE, sizeof(GTK_KDE_TYPE));
+
+ //fix the bug of using default KDE length -----------
+ key_data_pos[1] = (unsigned char)(6+((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16));
+ //------------------------------ david+2006-04-04
+
+ key_data_pos += sizeof(GTK_KDE_TYPE);
+
+ EapolKeyMsgSend.Octet[1] = 0x13;
+ // fill key-data length after encrypt --------------------
+#if 0
+ if (KeyDescriptorVer == key_desc_ver1) {
+ // david+2006-01-06, fix the bug of using 0 as group key id
+ // EapolKeyMsgSend.Octet[2] = 0x81;
+ Message_setKeyDescVer(EapolKeyMsgSend, key_desc_ver1);
+ Message_setKeyDataLength(EapolKeyMsgSend,
+ (sizeof(GTK_KDE_TYPE) + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16)));
+ }
+ else if (KeyDescriptorVer == key_desc_ver2) {
+ // david+2006-01-06, fix the bug of using 0 as group key id
+ // EapolKeyMsgSend.Octet[2] = 0x82;
+ Message_setKeyDescVer(EapolKeyMsgSend, key_desc_ver2);
+ Message_setKeyDataLength(EapolKeyMsgSend,
+ (sizeof(GTK_KDE_TYPE) + (8 + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16))));
+ }
+#endif
+ //------------------------------------- david+2006-04-04
+
+ memcpy(key_data_pos, pGblInfo->GTK[pGblInfo->GN], (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16);
+ EncGTK(priv, pstat, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC,
+ key_data,
+ sizeof(GTK_KDE_TYPE) + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16),
+ KeyData.Octet, &tmpKeyData_Length);
+ }
+ else
+#endif // RTL_WPA2
+ {
+ // fill key-data length after encrypt ---------------------
+#if 0
+ if (KeyDescriptorVer == key_desc_ver1)
+ Message_setKeyDataLength(EapolKeyMsgSend,
+ ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16));
+ else
+ Message_setKeyDataLength(EapolKeyMsgSend,
+ (8 + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16) ));
+#endif
+ //------------------------------------- david+2006-04-04
+ EncGTK(priv, pstat, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC,
+ pGblInfo->GTK[pGblInfo->GN],
+ (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16,
+ KeyData.Octet, &tmpKeyData_Length);
+ }
+
+ KeyData.Length = (int)tmpKeyData_Length;
+ Message_setKeyData(EapolKeyMsgSend, KeyData);
+
+ //set keyData length after encrypt ------------------
+ Message_setKeyDataLength(EapolKeyMsgSend, KeyData.Length);
+ //------------------------------- david+2006-04-04
+
+ /* Kenny
+ global->EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN +
+ ((global->RSNVariable.MulticastCipher == DOT11_ENC_TKIP) ? 32:16);
+ */
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + KeyData.Length;
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+ IfCalcMIC = TRUE;
+ break;
+ default:
+ DEBUG_ERR("Invalid wpa state [%x]\n", pStaInfo->state);
+ return;
+ }//switch
+
+ pStaInfo->EAPOLMsgSend.Length = EAPOLMsgSend.Length;
+ pStaInfo->EapolKeyMsgSend.Length = EapolKeyMsgSend.Length;
+
+send_packet:
+ eth_hdr = (struct wlan_ethhdr_t *)pStaInfo->EAPOLMsgSend.Octet;
+ memcpy(eth_hdr->daddr, pstat->hwaddr, 6);
+ memcpy(eth_hdr->saddr, GET_MY_HWADDR, 6);
+ eth_hdr->type = htons(LIB1X_ETHER_EAPOL_TYPE);
+
+ eapol = (struct lib1x_eapol *)(EAPOLMsgSend.Octet + ETHER_HDRLEN);
+ eapol->protocol_version = LIB1X_EAPOL_VER;
+ eapol->packet_type = LIB1X_EAPOL_KEY;
+ eapol->packet_body_length = htons(EapolKeyMsgSend.Length);
+
+ if (IfCalcMIC)
+ CalcMIC(EAPOLMsgSend, KeyDescriptorVer, pStaInfo->PTK, PTK_LEN_EAPOLMIC);
+
+ pskb = rtl_dev_alloc_skb(priv, MAX_EAPOLMSG_LEN, _SKB_TX_, 1);
+ if (pskb == NULL) {
+ DEBUG_ERR("Allocate EAP skb failed!\n");
+ return;
+ }
+ memcpy(pskb->data, (char *)eth_hdr, EAPOLMsgSend.Length);
+ skb_put(pskb, EAPOLMsgSend.Length);
+
+#ifdef DEBUG_PSK
+ { unsigned char *msg;
+ if (pStaInfo->state == PSK_STATE_PTKSTART)
+ msg = "4-1";
+ else if (pStaInfo->state == PSK_STATE_PTKINITNEGOTIATING)
+ msg = "4-3";
+ else
+ msg = "2-1";
+
+ printk("PSK: Send a EAPOL %s, len=%x\n", msg, pskb->len);
+ debug_out(NULL, pskb->data, pskb->len);
+ }
+#endif
+#ifdef ENABLE_RTL_SKB_STATS
+ rtl_atomic_dec(&priv->rtl_tx_skb_cnt);
+#endif
+
+ pskb->cb[0] = 7; // use highest priority to xmit
+ if (rtl8192cd_start_xmit(pskb, priv->dev))
+ rtl_kfree_skb(priv, pskb, _SKB_TX_);
+
+ mod_timer(&pstat->wpa_sta_info->resendTimer, jiffies + RESEND_TIME);
+}
+
+#ifdef CLIENT_MODE
+void ClientSendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend)
+{
+ OCTET_STRING IV, RSC, KeyID, MIC, KeyData, EAPOLMsgSend, EapolKeyMsgSend, Nonce;
+ unsigned char IV_buff[KEY_IV_LEN], RSC_buff[KEY_RSC_LEN];
+ unsigned char ID_buff[KEY_ID_LEN], MIC_buff[KEY_MIC_LEN], KEY_buff[INFO_ELEMENT_SIZE], Nonce_buff[KEY_NONCE_LEN];
+ struct wlan_ethhdr_t *eth_hdr;
+ struct lib1x_eapol *eapol;
+ struct sk_buff *pskb;
+ lib1x_eapol_key *eapol_key;
+ WPA_STA_INFO *pStaInfo;
+ WPA_GLOBAL_INFO *pGblInfo;
+ unsigned char KeyDescriptorVer = key_desc_ver1;
+ int send_report = 0;
+
+ DEBUG_TRACE;
+
+ if (priv == NULL || pstat == NULL)
+ return;
+
+ pStaInfo = pstat->wpa_sta_info;
+ pGblInfo = priv->wpa_global_info;
+
+ EAPOLMsgSend.Octet = pStaInfo->EAPOLMsgSend.Octet;
+ EapolKeyMsgSend.Octet = EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+ pStaInfo->EapolKeyMsgSend.Octet = EapolKeyMsgSend.Octet;
+ eapol_key = (lib1x_eapol_key *)EapolKeyMsgSend.Octet;
+
+ if (resend)
+ {
+ EAPOLMsgSend.Length = pStaInfo->EAPOLMsgSend.Length;
+ EapolKeyMsgSend.Length = pStaInfo->EapolKeyMsgSend.Length;
+ //---goto send_packet
+ }
+ else
+ {
+ IV.Octet = IV_buff;
+ IV.Length = KEY_IV_LEN;
+ RSC.Octet = RSC_buff;
+ RSC.Length = KEY_RSC_LEN;
+ KeyID.Octet = ID_buff;
+ KeyID.Length = KEY_ID_LEN;
+ MIC.Octet = MIC_buff;
+ MIC.Length = KEY_MIC_LEN;
+ KeyData.Octet = KEY_buff;
+ KeyData.Length = 0;
+
+ Nonce.Octet = Nonce_buff;
+ Nonce.Length = KEY_NONCE_LEN;
+
+ if (!pStaInfo->clientHndshkDone)
+ {
+ if (!pStaInfo->clientHndshkProcessing)
+ {
+ //send 2nd message of 4-way handshake
+ DEBUG_INFO("client mode 4-2\n");
+
+ pStaInfo->clientHndshkProcessing = TRUE;
+
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+
+ Message_setDescType(EapolKeyMsgSend, Message_DescType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyIndex(EapolKeyMsgSend, 0);
+ Message_setInstall(EapolKeyMsgSend, Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyAck(EapolKeyMsgSend, 0);
+ Message_setKeyMIC(EapolKeyMsgSend, 1);
+ Message_setSecure(EapolKeyMsgSend, Message_Secure(pStaInfo->EapolKeyMsgRecvd));
+ Message_setError(EapolKeyMsgSend, Message_Error(pStaInfo->EapolKeyMsgRecvd));
+ Message_setRequest(EapolKeyMsgSend, Message_Request(pStaInfo->EapolKeyMsgRecvd));
+ Message_setReserved(EapolKeyMsgSend, 0);
+
+ Message_setKeyLength(EapolKeyMsgSend, Message_KeyLength(pStaInfo->EapolKeyMsgRecvd));
+ Message_CopyReplayCounter(EapolKeyMsgSend, pStaInfo->EapolKeyMsgRecvd);
+
+ Message_setKeyNonce(EapolKeyMsgSend, pStaInfo->SNonce);
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+
+ Message_setKeyDataLength(EapolKeyMsgSend, pGblInfo->AuthInfoElement.Length);
+ Message_setKeyData(EapolKeyMsgSend, pGblInfo->AuthInfoElement);
+
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + pGblInfo->AuthInfoElement.Length;
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+
+ }
+ else
+ {
+ //Construct Message4
+ DEBUG_INFO("client mode 4-4\n");
+
+ pStaInfo->clientHndshkDone = TRUE;
+
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+
+ Message_setDescType(EapolKeyMsgSend, Message_DescType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyIndex(EapolKeyMsgSend, 0);
+ Message_setInstall(EapolKeyMsgSend, 0);
+ Message_setKeyAck(EapolKeyMsgSend, 0);
+ Message_setKeyMIC(EapolKeyMsgSend, 1);
+ Message_setSecure(EapolKeyMsgSend, Message_Secure(pStaInfo->EapolKeyMsgRecvd));
+ Message_setError(EapolKeyMsgSend, 0);
+ Message_setRequest(EapolKeyMsgSend, 0);
+ Message_setReserved(EapolKeyMsgSend, 0);
+ Message_setKeyLength(EapolKeyMsgSend, Message_KeyLength(pStaInfo->EapolKeyMsgRecvd));
+ Message_CopyReplayCounter(EapolKeyMsgSend, pStaInfo->EapolKeyMsgRecvd);
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+ Message_setKeyDataLength(EapolKeyMsgSend, 0);
+
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN;
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+
+ LOG_MSG( "Open and authenticated\n");
+
+ pStaInfo->clientMICReportReplayCounter.field.HighPart = 0;
+ pStaInfo->clientMICReportReplayCounter.field.LowPart = 0;
+ // printk("client mode 4-Way Message 4-4 done\n");
+ }
+ }
+ else
+ {
+ if (pStaInfo->clientGkeyUpdate) {
+ //send 2nd message of 2-way handshake
+ DEBUG_INFO("client mode 2-2\n");
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+
+ Message_setDescType(EapolKeyMsgSend, Message_DescType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd));
+ Message_setKeyIndex(EapolKeyMsgSend, pGblInfo->GN);
+ Message_setInstall(EapolKeyMsgSend, 0);
+ Message_setKeyAck(EapolKeyMsgSend, 0);
+ Message_setKeyMIC(EapolKeyMsgSend, 1);
+ Message_setSecure(EapolKeyMsgSend, 1);
+ Message_setError(EapolKeyMsgSend, 0);
+ Message_setRequest(EapolKeyMsgSend, 0);
+ Message_setReserved(EapolKeyMsgSend, 0);
+
+ Message_setKeyLength(EapolKeyMsgSend, Message_KeyLength(pStaInfo->EapolKeyMsgRecvd));
+ Message_CopyReplayCounter(EapolKeyMsgSend, pStaInfo->EapolKeyMsgRecvd);
+ memset(Nonce.Octet, 0, KEY_NONCE_LEN);
+ Message_setKeyNonce(EapolKeyMsgSend, Nonce);
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+ Message_setKeyDataLength(EapolKeyMsgSend, 0);
+
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN;
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+
+ // printk("client mode Group Message 2-2 done\n");
+ pStaInfo->clientGkeyUpdate = 0;
+ } else {
+ DEBUG_INFO("Send MIC Failure Report\n");
+ memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN);
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2)
+ Message_setDescType(EapolKeyMsgSend, desc_type_WPA2);
+ else
+#endif
+ Message_setDescType(EapolKeyMsgSend, desc_type_RSN);
+ if ((pGblInfo->MulticastCipher == _CCMP_PRIVACY_) || (pStaInfo->UnicastCipher == _CCMP_PRIVACY_))
+ KeyDescriptorVer = key_desc_ver2;
+ Message_setKeyDescVer(EapolKeyMsgSend, KeyDescriptorVer);
+ Message_setKeyType(EapolKeyMsgSend, 0);
+ Message_setKeyIndex(EapolKeyMsgSend, 0);
+ Message_setInstall(EapolKeyMsgSend, 0);
+ Message_setKeyAck(EapolKeyMsgSend, 0);
+ Message_setKeyMIC(EapolKeyMsgSend, 1);
+ Message_setSecure(EapolKeyMsgSend, 1);
+ Message_setError(EapolKeyMsgSend, 1);
+ Message_setRequest(EapolKeyMsgSend, 1);
+ Message_setReserved(EapolKeyMsgSend, 0);
+ Message_setKeyLength(EapolKeyMsgSend, 0);
+
+ Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->clientMICReportReplayCounter.field.HighPart, pStaInfo->clientMICReportReplayCounter.field.LowPart);
+ INCLargeInteger(&pStaInfo->clientMICReportReplayCounter);
+
+ memset(Nonce.Octet, 0, KEY_NONCE_LEN);
+ Message_setKeyNonce(EapolKeyMsgSend, Nonce);
+ memset(IV.Octet, 0, IV.Length);
+ Message_setKeyIV(EapolKeyMsgSend, IV);
+ memset(RSC.Octet, 0, RSC.Length);
+ Message_setKeyRSC(EapolKeyMsgSend, RSC);
+ memset(KeyID.Octet, 0, KeyID.Length);
+ Message_setKeyID(EapolKeyMsgSend, KeyID);
+ Message_setKeyDataLength(EapolKeyMsgSend, 0);
+
+ EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN;
+ EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length;
+ send_report = 1;
+ }
+ }
+ pStaInfo->EAPOLMsgSend.Length = EAPOLMsgSend.Length;
+ pStaInfo->EapolKeyMsgSend.Length = EapolKeyMsgSend.Length;
+ }
+
+ //send_packet--------------------------------------------------------------
+
+ eth_hdr = (struct wlan_ethhdr_t *)EAPOLMsgSend.Octet;
+ memcpy(eth_hdr->daddr, pstat->hwaddr, 6);
+ memcpy(eth_hdr->saddr, GET_MY_HWADDR, 6);
+ eth_hdr->type = htons(LIB1X_ETHER_EAPOL_TYPE);
+
+ eapol = (struct lib1x_eapol *)(EAPOLMsgSend.Octet + ETHER_HDRLEN);
+ eapol->protocol_version = LIB1X_EAPOL_VER;
+ eapol->packet_type = LIB1X_EAPOL_KEY;
+ eapol->packet_body_length = htons(EapolKeyMsgSend.Length);
+
+ if (!resend) {
+ if (send_report)
+ CalcMIC(EAPOLMsgSend, KeyDescriptorVer, pStaInfo->PTK, PTK_LEN_EAPOLMIC);
+ else
+ CalcMIC(EAPOLMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd), pStaInfo->PTK, PTK_LEN_EAPOLMIC);
+ }
+
+ pskb = rtl_dev_alloc_skb(priv, MAX_EAPOLMSG_LEN, _SKB_TX_, 1);
+
+ if (pskb == NULL) {
+ DEBUG_ERR("Allocate EAP skb failed!\n");
+ printk("Allocate EAP skb failed!\n");
+ return;
+ }
+
+ memcpy(pskb->data, (char *)eth_hdr, EAPOLMsgSend.Length);
+ skb_put(pskb, EAPOLMsgSend.Length);
+
+#ifdef ENABLE_RTL_SKB_STATS
+ rtl_atomic_dec(&priv->rtl_tx_skb_cnt);
+#endif
+
+ if (rtl8192cd_start_xmit(pskb, priv->dev))
+ rtl_kfree_skb(priv, pskb, _SKB_TX_);
+
+ if (!pStaInfo->clientHndshkDone) // only 4-2 need to check the time
+ mod_timer(&pStaInfo->resendTimer, jiffies + RESEND_TIME);
+
+ //--------------------------------------------------------------send_packet
+}
+#endif // CLIENT_MODE
+
+static void AuthenticationRequest(struct rtl8192cd_priv *priv, struct stat_info *pstat)
+{
+ static unsigned int RC_toggle = 0;
+
+ DEBUG_TRACE;
+
+ // For some STA that can only process if Replay Counter is not 0
+ if ((++RC_toggle)%2)
+ INCLargeInteger(&pstat->wpa_sta_info->CurrentReplayCounter);
+
+ INCOctet32_INTEGER(&priv->wpa_global_info->Counter);
+ SetNonce(pstat->wpa_sta_info->ANonce, priv->wpa_global_info->Counter);
+
+ memcpy(pstat->wpa_sta_info->PMK, priv->wpa_global_info->PSK, PMK_LEN);
+
+ //#ifdef RTL_WPA2
+#if 0
+ CalcPMKID( akm_sm->PMKID,
+ akm_sm->PMK, // PMK
+ global->theAuthenticator->global->TxRx->oursupp_addr, // AA
+ global->theAuthenticator->supp_addr); // SPA
+#endif
+ pstat->wpa_sta_info->state = PSK_STATE_PTKSTART;
+ pstat->wpa_sta_info->resendCnt = 0;
+
+ //send 1st message
+ SendEAPOL(priv, pstat, 0);
+}
+
+//-------------------------------------------------------------
+// Start 2-way handshake after receiving 4th message
+//-------------------------------------------------------------
+static void UpdateGK(struct rtl8192cd_priv *priv)
+{
+ WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info;
+ struct stat_info *pstat;
+ int i;
+
+ //------------------------------------------------------------
+ // Execute Global Group key state machine
+ //------------------------------------------------------------
+ if (pGblInfo->GTKAuthenticator && (pGblInfo->GTKRekey || pGblInfo->GInitAKeys)) {
+ pGblInfo->GTKRekey = FALSE;
+ pGblInfo->GInitAKeys = FALSE; // david+2006-04-04, fix the issue of re-generating group key
+
+ INCOctet32_INTEGER(&pGblInfo->Counter);
+
+ // kenny:??? GNonce should be a random number ???
+ SetNonce(pGblInfo->GNonce , pGblInfo->Counter);
+ CalcGTK(GET_MY_HWADDR, pGblInfo->GNonce.Octet,
+ pGblInfo->GMK, GMK_LEN, pGblInfo->GTK[pGblInfo->GN], GTK_LEN);
+
+#ifdef DEBUG_PSK
+ debug_out("PSK: Generated GTK=", pGblInfo->GTK[pGblInfo->GN], GTK_LEN);
+#endif
+
+ pGblInfo->GUpdateStationKeys = TRUE;
+ pGblInfo->GkeyReady = FALSE;
+
+ if (timer_pending(&pGblInfo->GKRekeyTimer))
+ del_timer_sync(&pGblInfo->GKRekeyTimer);
+
+ //---- In the case of updating GK to all STAs, only the STA that has finished
+ //---- 4-way handshake is needed to be sent with 2-way handshake
+ //gkm_sm->GKeyDoneStations = auth->NumOfSupplicant;
+ pGblInfo->GKeyDoneStations = 0;
+
+ for (i=0; i<NUM_STAT; i++) {
+ if (priv->pshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE)) {
+#if defined(UNIVERSAL_REPEATER) || defined(MBSSID)
+ if (priv != priv->pshare->aidarray[i]->priv)
+ continue;
+#endif
+
+ if ((priv->pshare->aidarray[i]->station.state & WIFI_ASOC_STATE) &&
+ (priv->pshare->aidarray[i]->station.wpa_sta_info->state == PSK_STATE_PTKINITDONE))
+ pGblInfo->GKeyDoneStations++;
+ }
+ }
+ }
+
+ //------------------------------------------------------------
+ // Execute Group key state machine of each STA
+ //------------------------------------------------------------
+ for (i=0; i<NUM_STAT; i++) {
+ if (priv->pshare->aidarray[i] == NULL)
+ continue;
+ pstat = &priv->pshare->aidarray[i]->station;
+ if ((priv->pshare->aidarray[i]->used != TRUE) ||!(pstat->state & WIFI_ASOC_STATE))
+ continue;
+
+#if defined(UNIVERSAL_REPEATER) || defined(MBSSID)
+ if (priv != priv->pshare->aidarray[i]->priv)
+ continue;
+#endif
+
+ //---- Group key handshake to only one supplicant ----
+ if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE &&
+ (pGblInfo->GkeyReady && pstat->wpa_sta_info->PInitAKeys)) {
+ pstat->wpa_sta_info->PInitAKeys = FALSE;
+ pstat->wpa_sta_info->gstate = PSK_GSTATE_REKEYNEGOTIATING; // set proper gstat, david+2006-04-06
+ pstat->wpa_sta_info->resendCnt = 0;
+ SendEAPOL(priv, pstat, 0);
+ }
+ //---- Updata group key to all supplicant----
+ else if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE && //Done 4-way handshake
+ (pGblInfo->GUpdateStationKeys || //When new key is generated
+ pstat->wpa_sta_info->gstate == PSK_GSTATE_REKEYNEGOTIATING)) { //1st message is not yet sent
+ pstat->wpa_sta_info->PInitAKeys = FALSE;
+ pstat->wpa_sta_info->gstate = PSK_GSTATE_REKEYNEGOTIATING; // set proper gstat, david+2006-04-06
+ pstat->wpa_sta_info->resendCnt = 0;
+ SendEAPOL(priv, pstat, 0);
+ }
+ }
+ pGblInfo->GUpdateStationKeys = FALSE;
+};
+
+static void EAPOLKeyRecvd(struct rtl8192cd_priv *priv, struct stat_info *pstat)
+{
+ WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info;
+ WPA_STA_INFO *pStaInfo = pstat->wpa_sta_info;
+ LARGE_INTEGER recievedRC;
+ struct lib1x_eapol *eapol;
+
+ DEBUG_TRACE;
+
+ eapol = ( struct lib1x_eapol * ) ( pstat->wpa_sta_info->EAPOLMsgRecvd.Octet + ETHER_HDRLEN );
+ if (eapol->packet_type != LIB1X_EAPOL_KEY) {
+#ifdef DEBUG_PSK
+ printk("Not Eapol-key pkt (type %d), drop\n", eapol->packet_type);
+#endif
+ return;
+ }
+
+ pStaInfo->EapolKeyMsgRecvd.Octet = pStaInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+
+#ifdef DEBUG_PSK
+ printk("PSK: Rx a EAPOL %s, len=%x\n", STATE2RXMSG(pstat), pStaInfo->EAPOLMsgRecvd.Length);
+ debug_out(NULL, pstat->wpa_sta_info->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Length);
+#endif
+
+ //----IEEE 802.11-03/156r2. MIC report : (1)MIC bit (2)error bit (3) request bit
+ //----Check if it is MIC failure report. If it is, indicate to driver
+ if (Message_KeyMIC(pStaInfo->EapolKeyMsgRecvd) && Message_Error(pStaInfo->EapolKeyMsgRecvd)
+ && Message_Request(pStaInfo->EapolKeyMsgRecvd)) {
+#ifdef DEBUG_PSK
+ printk("PSK: Rx MIC errir report from client\n");
+#endif
+ ToDrv_IndicateMICFail(priv, pstat->hwaddr);
+ return;
+ }
+
+ if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Pairwise) {
+ switch(pStaInfo->state) {
+ case PSK_STATE_PTKSTART:
+ //---- Receive 2nd message and send third
+ DEBUG_INFO("4-2\n");
+
+ //check replay counter
+ Message_ReplayCounter_OC2LI(pStaInfo->EapolKeyMsgRecvd, &recievedRC);
+ INCLargeInteger(&recievedRC);
+ if ( !(pStaInfo->CurrentReplayCounter.field.HighPart == recievedRC.field.HighPart
+ && pStaInfo->CurrentReplayCounter.field.LowPart == recievedRC.field.LowPart)) {
+ DEBUG_ERR("4-2: ERROR_NONEEQUL_REPLAYCOUNTER\n");
+ break;
+ }
+
+check_msg2:
+ // delete resend timer
+ if (timer_pending(&pStaInfo->resendTimer))
+ del_timer_sync(&pStaInfo->resendTimer);
+
+ pStaInfo->SNonce = Message_KeyNonce(pStaInfo->EapolKeyMsgRecvd);
+ CalcPTK(pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Octet + 6,
+ pStaInfo->ANonce.Octet, pStaInfo->SNonce.Octet,
+ pStaInfo->PMK, PMK_LEN, pStaInfo->PTK, PTK_LEN_TKIP);
+
+#ifdef DEBUG_PSK
+ debug_out("PSK: Generated PTK=", pStaInfo->PTK, PTK_LEN_TKIP);
+#endif
+
+ if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) {
+ if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) {
+ CalcPTK(pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Octet + 6,
+ pStaInfo->ANonce.Octet, pStaInfo->SNonce.Octet,
+ pGblInfo->PSKGuest, PMK_LEN, pStaInfo->PTK, PTK_LEN_TKIP);
+ if (CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) {
+ pStaInfo->isGuest = 1;
+ goto cont_msg;
+ }
+ }
+
+ DEBUG_ERR("4-2: ERROR_MIC_FAIL\n");
+#if 0
+ if (global->RSNVariable.PMKCached ) {
+ printf("\n%s:%d del_pmksa due to 4-2 ERROR_MIC_FAIL\n", (char *)__FUNCTION__, __LINE__);
+ global->RSNVariable.PMKCached = FALSE;
+ del_pmksa_by_spa(global->theAuthenticator->supp_addr);
+ }
+#endif
+
+ LOG_MSG("Authentication failled! (4-2: MIC error)\n");
+#if defined(CONFIG_RTL8186_KB_N)
+ authRes = 1;//Auth failed
+#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("Authentication failed;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]);
+#elif defined(CONFIG_RTL8196B_TLD)
+ LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %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
+
+ ToDrv_DisconnectSTA(priv, pstat, RSN_MIC_failure);
+ pStaInfo->state = PSK_STATE_IDLE;
+ break;
+ }
+cont_msg:
+ pStaInfo->resendCnt = 0;
+ pStaInfo->state = PSK_STATE_PTKINITNEGOTIATING;
+ SendEAPOL(priv, pstat, 0); // send msg 3
+ break;
+
+ case PSK_STATE_PTKINITNEGOTIATING:
+ //---- Receive 4th message ----
+ DEBUG_INFO("4-4\n");
+
+ // test 2nd or 4th message
+ // check replay counter to determine if msg 2 or 4 received --------------
+ // if ( Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd) != 0) {
+ if (Message_EqualReplayCounter(pStaInfo->ReplayCounterStarted, pStaInfo->EapolKeyMsgRecvd)) {
+ //---------------------------------------------------- david+1-12-2007
+
+ DEBUG_INFO("4-2 in akmsm_PTKINITNEGOTIATING: resend 4-3\n");
+
+#if 0 // Don't check replay counter during dup 4-2
+#ifdef RTL_WPA2
+ Message_ReplayCounter_OC2LI(global->EapolKeyMsgRecvd, &recievedRC);
+ INCLargeInteger(&recievedRC);
+ if ( !(global->akm_sm->CurrentReplayCounter.field.HighPart == recievedRC.field.HighPart
+ && global->akm_sm->CurrentReplayCounter.field.LowPart == recievedRC.field.LowPart))
+#else
+ if(!Message_EqualReplayCounter(global->akm_sm->CurrentReplayCounter, global->EapolKeyMsgRecvd))
+#endif
+ {
+#ifdef FOURWAY_DEBUG
+ printf("4-2: ERROR_NONEEQUL_REPLAYCOUNTER\n");
+ printf("global->akm_sm->CurrentReplayCounter.field.LowPart = %d\n", global->akm_sm->CurrentReplayCounter.field.LowPart);
+ printf("recievedRC.field.LowPart = %d\n", recievedRC.field.LowPart);
+#endif
+ retVal = ERROR_NONEEQUL_REPLAYCOUNTER;k
+ }else
+#endif // Don't check replay counter during dup 4-2
+ //#ifndef RTL_WPA2
+#if 0
+ // kenny: already increase CurrentReplayCounter after 4-1. Do it at the end of 4-2
+ INCLargeInteger(&global->akm_sm->CurrentReplayCounter);
+#endif
+
+ goto check_msg2;
+ }
+
+ // delete resend timer
+ if (timer_pending(&pStaInfo->resendTimer))
+ del_timer_sync(&pStaInfo->resendTimer);
+
+ if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { // errror
+ DEBUG_ERR("4-4: RSN_MIC_failure\n");
+#if 0
+ if (global->RSNVariable.PMKCached ) {
+ printf("\n%s:%d del_pmksa due to 4-4 RSN_MIC_failure\n", (char *)__FUNCTION__, __LINE__);
+ global->RSNVariable.PMKCached = FALSE;
+ del_pmksa_by_spa(global->theAuthenticator->supp_addr);
+ }
+#endif
+ LOG_MSG("Authentication failled! (4-4: MIC error)\n");
+#if defined(CONFIG_RTL8186_KB_N)
+ authRes = 1;//Auth failed
+#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("Authentication failed;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]);
+#elif defined(CONFIG_RTL8196B_TLD)
+ LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %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
+
+ ToDrv_DisconnectSTA(priv, pstat, RSN_MIC_failure);
+ pStaInfo->state = PSK_STATE_IDLE;
+ break;
+ }
+
+ LOG_MSG("Open and authenticated\n");
+
+#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("Authentication Success;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]);
+#elif defined(CONFIG_RTL8196B_TLD)
+ if (!list_empty(&priv->wlan_acl_list)) {
+ LOG_MSG_DEL("[WLAN access allowed] from MAC: %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
+
+ //#ifdef RTL_WPA2_PREAUTH
+#if 0
+ // update ANonce for next 4-way handshake
+ SetNonce(akm_sm->ANonce, global->auth->Counter);
+#endif
+
+ //MLME-SETKEYS.request
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+ // kenny: n+2
+ INCLargeInteger(&pStaInfo->CurrentReplayCounter);
+
+ ToDrv_SetPTK(priv, pstat);
+ if (pStaInfo->isGuest)
+ ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Guest);
+ else
+ ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Authorized);
+
+ // david+2006-04-04, fix the issue of re-generating group key, and need not
+ // update group key in WPA2
+ // pGblInfo->GInitAKeys = TRUE;
+#ifdef RTL_WPA2
+ if (!(pStaInfo->RSNEnabled & PSK_WPA2))
+#endif
+ pStaInfo->PInitAKeys = TRUE;
+ pStaInfo->state = PSK_STATE_PTKINITDONE;
+ pStaInfo->gstate = PSK_GSTATE_REKEYNEGOTIATING;
+
+ //lib1x_akmsm_UpdateGK_proc() calls lib1x_akmsm_SendEAPOL_proc for 2-way
+ //if group key sent is needed, send msg 1 of 2-way handshake
+#ifdef RTL_WPA2
+ if (pStaInfo->RSNEnabled & PSK_WPA2) {
+ //------------------------------------------------------
+ // Only when the group state machine is in the state of
+ // (1) The first STA Connected,
+ // (2) UPDATE GK to all station
+ // does the GKeyDoneStations needed to be decreased
+ //------------------------------------------------------
+
+ if(pGblInfo->GKeyDoneStations > 0)
+ pGblInfo->GKeyDoneStations--;
+
+ //Avaya akm_sm->TimeoutCtr = 0;
+ //To Do : set port secure to driver
+ // global->portSecure = TRUE;
+ //akm_sm->state = akmsm_PTKINITDONE;
+
+ pStaInfo->gstate = PSK_GSTATE_REKEYESTABLISHED;
+
+ if (pGblInfo->GKeyDoneStations==0 && !pGblInfo->GkeyReady) {
+ ToDrv_SetGTK(priv);
+ pGblInfo->GkeyReady = TRUE;
+ pGblInfo->GResetCounter = TRUE;
+
+ // start groupkey rekey timer
+ if (priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime)
+ mod_timer(&pGblInfo->GKRekeyTimer, jiffies + RTL_SECONDS_TO_JIFFIES(priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime));
+ }
+#if 0
+ if (global->RSNVariable.PMKCached) {
+ global->RSNVariable.PMKCached = FALSE; // reset
+ }
+#endif
+ DEBUG_INFO("\nWPA2: 4-way handshake done\n");
+ }
+#endif // RTL_WPA2
+
+ if (!Message_Secure(pStaInfo->EapolKeyMsgRecvd))
+ UpdateGK(priv); // send 2-1
+ break;
+
+ case PSK_STATE_PTKINITDONE:
+ // delete resend timer
+ if (timer_pending(&pStaInfo->resendTimer))
+ del_timer_sync(&pStaInfo->resendTimer);
+
+#if 0
+ //receive message [with request bit set]
+ if(Message_Request(global->EapolKeyMsgRecvd))
+ //supp request to initiate 4-way handshake
+ {
+
+ }
+#endif
+
+ //------------------------------------------------
+ // Supplicant request to init 4 or 2 way handshake
+ //------------------------------------------------
+ if (Message_Request(pStaInfo->EapolKeyMsgRecvd)) {
+ pStaInfo->state = PSK_STATE_PTKSTART;
+ if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Pairwise) {
+ if (Message_Error(pStaInfo->EapolKeyMsgRecvd))
+ IntegrityFailure(priv);
+ else {
+ if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Group) {
+ if (Message_Error(pStaInfo->EapolKeyMsgRecvd)) {
+ //auth change group key, initilate 4-way handshake with supp and execute
+ //the Group key handshake to all Supplicants
+ pGblInfo->GKeyFailure = TRUE;
+ IntegrityFailure(priv);
+ }
+ }
+ }
+ //---- Start 4-way handshake ----
+ pStaInfo->resendCnt = 0;
+ SendEAPOL(priv, pstat, 0);
+ }
+ //#ifdef RTL_WPA2_PREAUTH
+ // printf("kenny: %s() in akmsm_PTKINITDONE state. Call lib1x_akmsm_UpdateGK_proc()\n", (char *)__FUNCTION__);
+ //#endif
+ //---- Execute Group Key state machine for each STA ----
+ UpdateGK(priv);
+ }
+ else
+ {
+ }
+
+ break;
+ default:
+ break;
+
+ }//switch
+
+ }
+ else if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Group) {
+
+ // delete resend timer
+ if (timer_pending(&pStaInfo->resendTimer))
+ del_timer_sync(&pStaInfo->resendTimer);
+
+ //---- Receive 2nd message of 2-way handshake ----
+ DEBUG_INFO("2-2\n");
+ if (!Message_Request(pStaInfo->EapolKeyMsgRecvd)) {//2nd message of 2-way handshake
+ //verify that replay counter maches one it has used in the Group Key handshake
+ if (Message_LargerReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd)) {
+ DEBUG_ERR("ERROR_LARGER_REPLAYCOUNTER\n");
+ return;
+ }
+ if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) {
+ DEBUG_ERR("ERROR_MIC_FAIL\n");
+
+ LOG_MSG("2-way handshake failled! (2-2: MIC error)\n");
+#if defined(CONFIG_RTL8186_KB_N)
+ authRes = 1;//Auth failed
+#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("Authentication failed;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]);
+#elif defined(CONFIG_RTL8196B_TLD)
+ LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %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
+
+ ToDrv_DisconnectSTA(priv, pstat, RSN_MIC_failure);
+ pStaInfo->state = PSK_STATE_IDLE;
+ return;
+ }
+ }
+ else //if(!Message_Request(global->EapolKeyMsgRecvd))
+ //supp request to change group key
+ {
+ }
+
+ //------------------------------------------------------
+ // Only when the group state machine is in the state of
+ // (1) The first STA Connected,
+ // (2) UPDATE GK to all station
+ // does the GKeyDoneStations needed to be decreased
+ //------------------------------------------------------
+
+ if (pGblInfo->GKeyDoneStations > 0)
+ pGblInfo->GKeyDoneStations--;
+
+ //Avaya akm_sm->TimeoutCtr = 0;
+ //To Do : set port secure to driver
+ pStaInfo->gstate = PSK_GSTATE_REKEYESTABLISHED;
+
+ if (pGblInfo->GKeyDoneStations == 0 && !pGblInfo->GkeyReady) {
+ ToDrv_SetGTK(priv);
+ DEBUG_INFO("2-way Handshake is finished\n");
+ pGblInfo->GkeyReady = TRUE;
+ pGblInfo->GResetCounter = TRUE;
+
+ // start groupkey rekey timer
+ if (priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime)
+ mod_timer(&pGblInfo->GKRekeyTimer, jiffies + RTL_SECONDS_TO_JIFFIES(priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime));
+ }
+ else {
+ DEBUG_INFO(" Receive bad group key handshake");
+ }
+ }
+ }
+
+#ifdef CLIENT_MODE
+ static void ClientEAPOLKeyRecvd(struct rtl8192cd_priv *priv, struct stat_info *pstat)
+ {
+ WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info;
+ WPA_STA_INFO *pStaInfo = pstat->wpa_sta_info;
+ LARGE_INTEGER recievedRC;
+ struct lib1x_eapol *eapol;
+ int toSetKey = 0;
+
+ eapol = ( struct lib1x_eapol * ) ( pstat->wpa_sta_info->EAPOLMsgRecvd.Octet + ETHER_HDRLEN );
+ if (eapol->packet_type != LIB1X_EAPOL_KEY)
+ {
+#ifdef DEBUG_PSK
+ printk("Not Eapol-key pkt (type %d), drop\n", eapol->packet_type);
+#endif
+ return;
+ }
+
+ pStaInfo->EapolKeyMsgRecvd.Octet = pStaInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN;
+
+#ifdef DEBUG_PSK
+ debug_out(NULL, pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Length);
+#endif
+
+ if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Pairwise) {
+
+ if (Message_KeyMIC(pStaInfo->EapolKeyMsgRecvd) == FALSE)
+ {
+ //---- Receive 1st message and send 2nd
+ DEBUG_INFO("client mode 4-1\n");
+
+ if (timer_pending(&pStaInfo->resendTimer))
+ del_timer_sync(&pStaInfo->resendTimer);
+
+
+ if(pStaInfo->clientHndshkDone || pStaInfo->clientHndshkProcessing)
+ {
+ DEBUG_INFO("AP trigger pairwise rekey\n");
+
+ //reset the client info-------------------------------------------------------
+ pStaInfo->CurrentReplayCounter.field.HighPart = 0xffffffff;
+ pStaInfo->CurrentReplayCounter.field.LowPart = 0xffffffff;
+
+ pStaInfo->clientHndshkProcessing = FALSE;
+ pStaInfo->clientHndshkDone = FALSE;
+
+ pGblInfo->GkeyReady = FALSE;
+
+ //-------------------------------------------------------reset the client info
+ }
+
+ //check replay counter
+ if(!Message_DefaultReplayCounter(pStaInfo->CurrentReplayCounter) &&
+ Message_SmallerEqualReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd) )
+ {
+ DEBUG_ERR("client mode 4-1: ERROR_NONEEQUL_REPLAYCOUNTER\n");
+ return;
+ }
+
+
+ //set wpa_sta_info parameter----------------------------------------------------
+ pstat->wpa_sta_info->RSNEnabled = priv->pmib->dot1180211AuthEntry.dot11EnablePSK;
+ if (pstat->wpa_sta_info->RSNEnabled == 1) {
+ if (priv->pmib->dot1180211AuthEntry.dot11WPACipher == 2)
+ pstat->wpa_sta_info->UnicastCipher = 0x2;
+ else if (priv->pmib->dot1180211AuthEntry.dot11WPACipher == 8)
+ pstat->wpa_sta_info->UnicastCipher = 0x4;
+ else
+ printk("unicastcipher in wpa = nothing\n");
+ }
+ else if (pstat->wpa_sta_info->RSNEnabled == 2) {
+ if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 2)
+ pstat->wpa_sta_info->UnicastCipher = 0x2;
+ else if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 8)
+ pstat->wpa_sta_info->UnicastCipher = 0x4;
+ else
+ printk("unicastcipher in wpa = nothing\n");
+ }
+ //----------------------------------------------------set wpa_sta_info parameter
+
+ INCOctet32_INTEGER(&pGblInfo->Counter);
+ SetNonce(pStaInfo->SNonce, pGblInfo->Counter);
+
+ pStaInfo->ANonce = Message_KeyNonce(pStaInfo->EapolKeyMsgRecvd);
+ CalcPTK(pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Octet + 6,
+ pStaInfo->ANonce.Octet, pStaInfo->SNonce.Octet,
+ pStaInfo->PMK, PMK_LEN, pStaInfo->PTK, PTK_LEN_TKIP);
+
+#ifdef DEBUG_PSK
+ debug_out("PSK: Generated PTK=", pStaInfo->PTK, PTK_LEN_TKIP);
+#endif
+
+ //pStaInfo->clientHndshkProcessing = TRUE;-----------leave it to sendeapol
+ ClientSendEAPOL(priv, pstat, 0); // send msg 2
+ }
+ else
+ {
+ //---- Receive 3rd message ----
+ DEBUG_INFO("client mode 4-3\n");
+
+ pStaInfo->resendCnt = 0; //victoryman
+
+ if (!pStaInfo->clientHndshkProcessing)
+ {
+ DEBUG_ERR("client mode 4-3: ERROR_MSG_1_ABSENT\n");
+ return;
+ }
+
+ // delete resend timer
+ if (timer_pending(&pStaInfo->resendTimer))
+ del_timer_sync(&pStaInfo->resendTimer);
+
+ Message_ReplayCounter_OC2LI(pStaInfo->EapolKeyMsgRecvd, &recievedRC);
+ if(!Message_DefaultReplayCounter(pStaInfo->CurrentReplayCounter) &&
+ Message_SmallerEqualReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd) )
+ {
+ DEBUG_ERR("client mode 4-3: ERROR_NONEEQUL_REPLAYCOUNTER\n");
+ return;
+ }
+ else if (!Message_EqualKeyNonce(pStaInfo->EapolKeyMsgRecvd, pStaInfo->ANonce))
+ {
+ DEBUG_ERR("client mode 4-3: ANonce not equal\n");
+ return;
+ }
+ else if(!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC))
+ {
+ DEBUG_ERR("client mode 4-3: PTK MIC ERROR\n");
+ LOG_MSG("Authentication failled! (4-3: MIC error)\n");
+#if defined(CONFIG_RTL8186_KB_N)
+ authRes = 1;//Auth failed
+#endif
+ return;
+ }
+
+ pStaInfo->CurrentReplayCounter.field.HighPart = recievedRC.field.HighPart;
+ pStaInfo->CurrentReplayCounter.field.LowPart = recievedRC.field.LowPart;
+
+ if ((pStaInfo->RSNEnabled & PSK_WPA2) && (Message_DescType(pStaInfo->EapolKeyMsgRecvd) == desc_type_WPA2))
+ {
+ unsigned char decrypted_data[128];
+ unsigned char GTK_KDE_OUI[] = { 0x00, 0x0F, 0xAC, 0x01 };
+ unsigned char WPA_IE_OUI[] = { 0x00, 0x50, 0xF2, 0x01 };
+ unsigned char *pGTK_KDE;
+ unsigned char *pKeyData;
+ unsigned short keyDataLength;
+
+ keyDataLength = Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd);
+ pKeyData = pStaInfo->EapolKeyMsgRecvd.Octet + KeyDataPos;
+
+ if(!DecWPA2KeyData(pStaInfo, pKeyData, keyDataLength, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC
+ , decrypted_data))
+ {
+ DEBUG_ERR("client mode 4-3: ERROR_AESKEYWRAP_MIC_FAIL\n");
+ LOG_MSG("Authentication failled! (4-3: ERROR_AESKEYWRAP_MIC_FAIL)\n");
+#if defined(CONFIG_RTL8186_KB_N)
+ authRes = 1;//Auth failed
+#endif
+ return;
+ }
+
+ //wpa2_hexdump("4-3 KeyData (Decrypted)",decrypted_data,keyDataLength);
+ if ( decrypted_data[0] == WPA2_ELEMENT_ID)
+ {
+ pGTK_KDE = &decrypted_data[2] + (unsigned char)decrypted_data[1];
+ if ( *pGTK_KDE == WPA2_ELEMENT_ID )
+ { // The second optional RSNIE is present
+ DEBUG_ERR("client mode 4-3: The second optional RSNIE is present! Cannot handle it yet!\n");
+ return;
+ }
+ else if ( *pGTK_KDE == WPA_ELEMENT_ID )
+ {
+ // if contain RSN IE, skip it
+ if (!memcmp((pGTK_KDE+2), WPA_IE_OUI, sizeof(WPA_IE_OUI)))
+ pGTK_KDE += (unsigned char)*(pGTK_KDE+1) + 2;
+
+ if (!memcmp((pGTK_KDE+2), GTK_KDE_OUI, sizeof(GTK_KDE_OUI)))
+ {
+ // GTK Key Data Encapsulation Format
+ unsigned char gtk_len = (unsigned char)*(pGTK_KDE+1) - 6;
+ unsigned char keyID = (unsigned char)*(pGTK_KDE+6) & 0x03;
+ pGblInfo->GN = keyID;
+ memcpy(pGblInfo->GTK[keyID], (pGTK_KDE+8), gtk_len);
+ toSetKey = 1;
+ pGblInfo->GkeyReady = TRUE;
+ }
+ }
+
+ //check AP's RSNIE and set Group Key Chiper
+ if (decrypted_data[7] == _TKIP_PRIVACY_)
+ pGblInfo->MulticastCipher = _TKIP_PRIVACY_ ;
+ else if (decrypted_data[7] == _CCMP_PRIVACY_)
+ pGblInfo->MulticastCipher = _CCMP_PRIVACY_ ;
+ }
+ }
+ else if ((pStaInfo->RSNEnabled & PSK_WPA) && (Message_DescType(pStaInfo->EapolKeyMsgRecvd) == desc_type_RSN))
+ {
+ unsigned char WPAkeyData[255];
+ unsigned short DataLength;
+ memset(WPAkeyData, 0, 255);
+ DataLength = Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd);
+ memcpy(WPAkeyData, pStaInfo->EapolKeyMsgRecvd.Octet+KeyDataPos, 255);
+
+ //check AP's RSNIE and set Group Key Chiper
+ if (WPAkeyData[11] == _TKIP_PRIVACY_)
+ pGblInfo->MulticastCipher = _TKIP_PRIVACY_ ;
+ else if (WPAkeyData[11] == _CCMP_PRIVACY_)
+ pGblInfo->MulticastCipher = _CCMP_PRIVACY_ ;
+ }
+
+ ClientSendEAPOL(priv, pstat, 0); // send msg 4
+
+ if (toSetKey)
+ {
+ ToDrv_SetGTK(priv);
+ toSetKey = 0;
+ }
+ ToDrv_SetPTK(priv, pstat);
+ ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Authorized);
+ }
+ }
+ else if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Group) {
+
+ unsigned char decrypted_data[128];
+ unsigned char GTK_KDE_OUI[] = { 0x00, 0x0F, 0xAC, 0x01 };
+ unsigned char *pGTK_KDE;
+ unsigned char keyID;
+
+ //---- Receive 1st message of 2-way handshake ----
+ DEBUG_INFO("client mode receive 2-1\n");
+
+ pStaInfo->resendCnt = 0; //victoryman
+
+ Message_ReplayCounter_OC2LI(pStaInfo->EapolKeyMsgRecvd, &recievedRC);
+
+ if(Message_SmallerEqualReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd) )
+ {
+ DEBUG_ERR("client mode 2-1: ERROR_NONEEQUL_REPLAYCOUNTER\n");
+ return;
+ }
+ else if(!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC))
+ {
+ DEBUG_ERR("client mode 2-1: ERROR_MIC_FAIL\n");
+ LOG_MSG("Authentication failled! (4-2: MIC error)\n");
+#if defined(CONFIG_RTL8186_KB_N)
+ authRes = 1;//Auth failed
+#endif
+ return;
+ }
+ else if(!DecGTK(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC,
+ ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16),
+ pGblInfo->GTK[Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd)]))
+ {
+ DEBUG_ERR("client mode 2-1: ERROR_AESKEYWRAP_MIC_FAIL\n");
+ return;
+ }
+
+ keyID = Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd);
+ if ((pStaInfo->RSNEnabled & PSK_WPA2) && (Message_DescType(pStaInfo->EapolKeyMsgRecvd) == desc_type_WPA2))
+ {
+ memcpy(decrypted_data, pGblInfo->GTK[keyID], Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd));
+ pGTK_KDE = decrypted_data;
+ if ( *pGTK_KDE == WPA_ELEMENT_ID && !memcmp((pGTK_KDE+2), GTK_KDE_OUI, sizeof(GTK_KDE_OUI)))
+ {
+ // GTK Key Data Encapsulation Format
+ unsigned char gtk_len = (unsigned char)*(pGTK_KDE+1) - 6;
+ keyID = (unsigned char)*(pGTK_KDE+6) & 0x03;
+ pGblInfo->GN = keyID;
+ memcpy(pGblInfo->GTK[keyID], (pGTK_KDE+8), gtk_len);
+ }
+ }
+ else
+ {
+ pGblInfo->GN = keyID;
+ }
+ //MLME_SETKEYS.request() to set Group Key;
+ pGblInfo->GkeyReady = TRUE;
+
+ pStaInfo->CurrentReplayCounter.field.HighPart = recievedRC.field.HighPart;
+ pStaInfo->CurrentReplayCounter.field.LowPart = recievedRC.field.LowPart;
+ pStaInfo->clientGkeyUpdate = 1;
+
+ ToDrv_SetGTK(priv);
+ ClientSendEAPOL(priv, pstat, 0); // send msg 2-1
+ }
+ else
+ printk("Client EAPOL Key Receive ERROR!!\n");
+ }
+#endif // CLIENT_MODE
+
+
+ void derivePSK(struct rtl8192cd_priv *priv)
+ {
+ WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info;
+
+ if (strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhrase) == 64) // hex
+ get_array_val(pGblInfo->PSK, priv->pmib->dot1180211AuthEntry.dot11PassPhrase, 64);
+ else
+ PasswordHash(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, SSID, SSID_LEN,
+ pGblInfo->PSK);
+
+ if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) {
+ if (strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest) == 64)
+ get_array_val(pGblInfo->PSKGuest, priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, 64);
+ else
+ PasswordHash(priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, SSID, SSID_LEN,
+ pGblInfo->PSKGuest);
+ }
+ }
+
+ void 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));
+
+ //---- Counter is initialized whenever boot time ----
+ GenNonce(pGblInfo->Counter.charData, (unsigned char*)"addr");
+
+ if (OPMODE & WIFI_AP_STATE)
+ {
+ //---- Initialize Goup Key state machine ----
+ pGblInfo->GNonce.Octet = pGblInfo->GNonceBuf;
+ pGblInfo->GNonce.Length = KEY_NONCE_LEN;
+ pGblInfo->GTKAuthenticator = TRUE;
+ pGblInfo->GN = 1;
+ pGblInfo->GM = 2;
+ pGblInfo->GInitAKeys = TRUE; // david+2006-04-04, fix the issue of re-generating group key
+
+ init_timer(&pGblInfo->GKRekeyTimer);
+ pGblInfo->GKRekeyTimer.data = (unsigned long)priv;
+ pGblInfo->GKRekeyTimer.function = GKRekeyTimeout;
+ }
+#if 0
+ if (strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhrase) == 64) // hex
+ get_array_val(pGblInfo->PSK, priv->pmib->dot1180211AuthEntry.dot11PassPhrase, 64);
+ else
+ PasswordHash(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID,
+ pGblInfo->PSK);
+
+ if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) {
+ if (strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest) == 64)
+ get_array_val(pGblInfo->PSKGuest, priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, 64);
+ else
+ PasswordHash(priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID,
+ pGblInfo->PSKGuest);
+ }
+#else
+ derivePSK(priv);
+#endif
+#ifdef DEBUG_PSK
+ debug_out("PSK: PMK=", pGblInfo->PSK, PMK_LEN);
+ if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0])
+ debug_out("PSK-Guest: PMK=", pGblInfo->PSKGuest, PMK_LEN);
+#endif
+
+ 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 CLIENT_MODE
+ if((OPMODE & WIFI_ADHOC_STATE)&&(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & 2)) // if WPA2
+ low_cipher = 0;
+#endif
+
+#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;
+
+ ConstructIE(priv, pGblInfo->AuthInfoElement.Octet,
+ &pGblInfo->AuthInfoElement.Length);
+
+ ToDrv_SetIE(priv);
+ }
+
+#if defined(WDS) && defined(INCLUDE_WPA_PSK)
+ void wds_psk_set(struct rtl8192cd_priv *priv, int idx, unsigned char *key)
+ {
+ 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
+ }
+
+
+ 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);
+ }
+ }
+#endif
+
+ int 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
+ AuthenticationRequest(priv, pstat); // send 4-1
+ }
+ }
+ else { // RNSIE is null
+ if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK)
+ ToDrv_RspAssoc(priv, id, mac, -ERROR_INVALID_RSNIE);
+ }
+ }
+#ifdef CLIENT_MODE
+ else
+ mod_timer(&pstat->wpa_sta_info->resendTimer, jiffies + WAIT_EAP_TIME);
+#endif
+ break;
+
+ case DOT11_EVENT_DISASSOCIATION_IND:
+ reset_sta_info(priv, pstat);
+ break;
+
+ case DOT11_EVENT_EAP_PACKET:
+ if (OPMODE & WIFI_AP_STATE) {
+ if (pstat->wpa_sta_info->state == PSK_STATE_IDLE) {
+ DEBUG_ERR("Rx EAPOL packet but did not get Assoc-Ind yet!\n");
+ break;
+ }
+ }
+
+ if (len > MAX_EAPOLMSG_LEN) {
+ DEBUG_ERR("Rx EAPOL packet which length is too long [%x]!\n", len);
+ break;
+ }
+
+#ifdef CLIENT_MODE
+ if ((OPMODE & WIFI_STATION_STATE) &&
+ !(pstat->wpa_sta_info->clientHndshkProcessing||pstat->wpa_sta_info->clientHndshkDone)) {
+#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;
+ }
+ LOG_MSG("%s-%s PSK authentication in progress...\n", (isWPA2 ? "WPA2" : "WPA"), pmsg);
+#endif
+ reset_sta_info(priv, pstat);
+ }
+#endif
+ memcpy(pstat->wpa_sta_info->EAPOLMsgRecvd.Octet, msg, len);
+ pstat->wpa_sta_info->EAPOLMsgRecvd.Length = len;
+ if (OPMODE & WIFI_AP_STATE)
+ EAPOLKeyRecvd(priv, pstat);
+#ifdef CLIENT_MODE
+ else if (OPMODE & WIFI_STATION_STATE)
+ ClientEAPOLKeyRecvd(priv, pstat);
+#endif
+ break;
+
+ case DOT11_EVENT_MIC_FAILURE:
+#ifdef CLIENT_MODE
+ if (OPMODE & WIFI_STATION_STATE)
+ ClientSendEAPOL(priv, pstat, 0);
+#endif
+ break;
+
+ // button 2009.05.21
+ case DOT11_EVENT_WPA_MULTICAST_CIPHER:
+ case DOT11_EVENT_WPA2_MULTICAST_CIPHER:
+#ifdef CLIENT_MODE
+ if (OPMODE & WIFI_STATION_STATE)
+ {
+ priv->wpa_global_info->MulticastCipher = *msg;
+ ConstructIE(priv, priv->wpa_global_info->AuthInfoElement.Octet,
+ &priv->wpa_global_info->AuthInfoElement.Length);
+ memcpy((void *)priv->pmib->dot11RsnIE.rsnie, priv->wpa_global_info->AuthInfoElement.Octet
+ , priv->wpa_global_info->AuthInfoElement.Length);
+ DEBUG_WARN("####### MulticastCipher=%d\n", priv->wpa_global_info->MulticastCipher);
+ }
+#endif
+ break;
+ }
+
+ return 0;
+ }
+
+#endif // INCLUDE_WPA_PSK
+
+