linux/drivers/staging/rt3090/common/cmm_wpa.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26
  27        Module Name:
  28        wpa.c
  29
  30        Abstract:
  31
  32        Revision History:
  33        Who                     When                    What
  34        --------        ----------              ----------------------------------------------
  35        Jan     Lee             03-07-22                Initial
  36        Paul Lin        03-11-28                Modify for supplicant
  37*/
  38
  39#include "../rt_config.h"
  40
  41
  42// WPA OUI
  43UCHAR           OUI_WPA_NONE_AKM[4]             = {0x00, 0x50, 0xF2, 0x00};
  44UCHAR       OUI_WPA_VERSION[4]      = {0x00, 0x50, 0xF2, 0x01};
  45UCHAR       OUI_WPA_WEP40[4]      = {0x00, 0x50, 0xF2, 0x01};
  46UCHAR       OUI_WPA_TKIP[4]     = {0x00, 0x50, 0xF2, 0x02};
  47UCHAR       OUI_WPA_CCMP[4]     = {0x00, 0x50, 0xF2, 0x04};
  48UCHAR       OUI_WPA_WEP104[4]      = {0x00, 0x50, 0xF2, 0x05};
  49UCHAR       OUI_WPA_8021X_AKM[4]        = {0x00, 0x50, 0xF2, 0x01};
  50UCHAR       OUI_WPA_PSK_AKM[4]      = {0x00, 0x50, 0xF2, 0x02};
  51// WPA2 OUI
  52UCHAR       OUI_WPA2_WEP40[4]   = {0x00, 0x0F, 0xAC, 0x01};
  53UCHAR       OUI_WPA2_TKIP[4]        = {0x00, 0x0F, 0xAC, 0x02};
  54UCHAR       OUI_WPA2_CCMP[4]        = {0x00, 0x0F, 0xAC, 0x04};
  55UCHAR       OUI_WPA2_8021X_AKM[4]   = {0x00, 0x0F, 0xAC, 0x01};
  56UCHAR       OUI_WPA2_PSK_AKM[4]         = {0x00, 0x0F, 0xAC, 0x02};
  57UCHAR       OUI_WPA2_WEP104[4]   = {0x00, 0x0F, 0xAC, 0x05};
  58
  59
  60
  61static VOID     ConstructEapolKeyData(
  62        IN      PMAC_TABLE_ENTRY        pEntry,
  63        IN      UCHAR                   GroupKeyWepStatus,
  64        IN      UCHAR                   keyDescVer,
  65        IN      UCHAR                   MsgType,
  66        IN      UCHAR                   DefaultKeyIdx,
  67        IN      UCHAR                   *GTK,
  68        IN      UCHAR                   *RSNIE,
  69        IN      UCHAR                   RSNIE_LEN,
  70        OUT PEAPOL_PACKET   pMsg);
  71
  72static VOID     CalculateMIC(
  73        IN      UCHAR                   KeyDescVer,
  74        IN      UCHAR                   *PTK,
  75        OUT PEAPOL_PACKET   pMsg);
  76
  77static VOID WpaEAPPacketAction(
  78    IN PRTMP_ADAPTER pAd,
  79    IN MLME_QUEUE_ELEM *Elem);
  80
  81static VOID WpaEAPOLASFAlertAction(
  82    IN PRTMP_ADAPTER pAd,
  83    IN MLME_QUEUE_ELEM *Elem);
  84
  85static VOID WpaEAPOLLogoffAction(
  86    IN PRTMP_ADAPTER pAd,
  87    IN MLME_QUEUE_ELEM *Elem);
  88
  89static VOID WpaEAPOLStartAction(
  90    IN PRTMP_ADAPTER    pAd,
  91    IN MLME_QUEUE_ELEM  *Elem);
  92
  93static VOID WpaEAPOLKeyAction(
  94    IN PRTMP_ADAPTER    pAd,
  95    IN MLME_QUEUE_ELEM  *Elem);
  96
  97/*
  98    ==========================================================================
  99    Description:
 100        association state machine init, including state transition and timer init
 101    Parameters:
 102        S - pointer to the association state machine
 103    ==========================================================================
 104 */
 105VOID WpaStateMachineInit(
 106    IN  PRTMP_ADAPTER   pAd,
 107    IN  STATE_MACHINE *S,
 108    OUT STATE_MACHINE_FUNC Trans[])
 109{
 110    StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE);
 111
 112    StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, (STATE_MACHINE_FUNC)WpaEAPPacketAction);
 113    StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, (STATE_MACHINE_FUNC)WpaEAPOLStartAction);
 114    StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, (STATE_MACHINE_FUNC)WpaEAPOLLogoffAction);
 115    StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
 116    StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, (STATE_MACHINE_FUNC)WpaEAPOLASFAlertAction);
 117}
 118
 119/*
 120    ==========================================================================
 121    Description:
 122        this is state machine function.
 123        When receiving EAP packets which is  for 802.1x authentication use.
 124        Not use in PSK case
 125    Return:
 126    ==========================================================================
 127*/
 128VOID WpaEAPPacketAction(
 129    IN PRTMP_ADAPTER pAd,
 130    IN MLME_QUEUE_ELEM *Elem)
 131{
 132}
 133
 134VOID WpaEAPOLASFAlertAction(
 135    IN PRTMP_ADAPTER pAd,
 136    IN MLME_QUEUE_ELEM *Elem)
 137{
 138}
 139
 140VOID WpaEAPOLLogoffAction(
 141    IN PRTMP_ADAPTER pAd,
 142    IN MLME_QUEUE_ELEM *Elem)
 143{
 144}
 145
 146/*
 147    ==========================================================================
 148    Description:
 149       Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
 150    Return:
 151    ==========================================================================
 152*/
 153VOID WpaEAPOLStartAction(
 154    IN PRTMP_ADAPTER    pAd,
 155    IN MLME_QUEUE_ELEM  *Elem)
 156{
 157    MAC_TABLE_ENTRY     *pEntry;
 158    PHEADER_802_11      pHeader;
 159
 160    DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
 161
 162    pHeader = (PHEADER_802_11)Elem->Msg;
 163
 164    //For normaol PSK, we enqueue an EAPOL-Start command to trigger the process.
 165    if (Elem->MsgLen == 6)
 166        pEntry = MacTableLookup(pAd, Elem->Msg);
 167    else
 168    {
 169        pEntry = MacTableLookup(pAd, pHeader->Addr2);
 170    }
 171
 172    if (pEntry)
 173    {
 174                DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx));
 175
 176        if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
 177                        && (pEntry->WpaState < AS_PTKSTART)
 178            && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND))))
 179        {
 180            pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
 181            pEntry->WpaState = AS_INITPSK;
 182            pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
 183            NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
 184            pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
 185
 186            WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
 187        }
 188    }
 189}
 190
 191/*
 192    ==========================================================================
 193    Description:
 194        This is state machine function.
 195        When receiving EAPOL packets which is  for 802.1x key management.
 196        Use both in WPA, and WPAPSK case.
 197        In this function, further dispatch to different functions according to the received packet.  3 categories are :
 198          1.  normal 4-way pairwisekey and 2-way groupkey handshake
 199          2.  MIC error (Countermeasures attack)  report packet from STA.
 200          3.  Request for pairwise/group key update from STA
 201    Return:
 202    ==========================================================================
 203*/
 204VOID WpaEAPOLKeyAction(
 205    IN PRTMP_ADAPTER    pAd,
 206    IN MLME_QUEUE_ELEM  *Elem)
 207{
 208    MAC_TABLE_ENTRY     *pEntry;
 209    PHEADER_802_11      pHeader;
 210    PEAPOL_PACKET       pEapol_packet;
 211        KEY_INFO                        peerKeyInfo;
 212
 213    DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
 214
 215    pHeader = (PHEADER_802_11)Elem->Msg;
 216    pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 217
 218        NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
 219        NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO));
 220
 221        hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
 222
 223        *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
 224
 225    do
 226    {
 227        pEntry = MacTableLookup(pAd, pHeader->Addr2);
 228
 229                if (!pEntry || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
 230            break;
 231
 232                if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
 233                                break;
 234
 235                DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr)));
 236
 237        if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) ||
 238                        ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC)))
 239        {
 240            DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
 241            break;
 242        }
 243
 244                // The value 1 shall be used for all EAPOL-Key frames to and from a STA when
 245                // neither the group nor pairwise ciphers are CCMP for Key Descriptor 1.
 246                if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP))
 247        {
 248                DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n"));
 249            break;
 250        }
 251                // The value 2 shall be used for all EAPOL-Key frames to and from a STA when
 252                // either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2.
 253        else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES))
 254        {
 255                DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) \n"));
 256                break;
 257        }
 258
 259                // Check if this STA is in class 3 state and the WPA state is started
 260        if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK))
 261        {
 262                        // Check the Key Ack (bit 7) of the Key Information to determine the Authenticator
 263                        // or not.
 264                        // An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL-
 265                        // Key frame from the Authenticator must not have the Ack bit set.
 266                        if (peerKeyInfo.KeyAck == 1)
 267                        {
 268                                // The frame is snet by Authenticator.
 269                                // So the Supplicant side shall handle this.
 270
 271                                if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) &&
 272                                        (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY))
 273                                {
 274                                        // Process 1. the message 1 of 4-way HS in WPA or WPA2
 275                                        //                        EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1)
 276                                        //                 2. the message 3 of 4-way HS in WPA
 277                                        //                        EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3)
 278                                        if (peerKeyInfo.KeyMic == 0)
 279                        PeerPairMsg1Action(pAd, pEntry, Elem);
 280                        else
 281                        PeerPairMsg3Action(pAd, pEntry, Elem);
 282                                }
 283                                else if ((peerKeyInfo.Secure == 1) &&
 284                                                 (peerKeyInfo.KeyMic == 1) &&
 285                                                 (peerKeyInfo.Request == 0) &&
 286                                                 (peerKeyInfo.Error == 0))
 287                                {
 288                                        // Process 1. the message 3 of 4-way HS in WPA2
 289                                        //                        EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3)
 290                                        //                 2. the message 1 of group KS in WPA or WPA2
 291                                        //                        EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N])
 292                                        if (peerKeyInfo.KeyType == PAIRWISEKEY)
 293                                                PeerPairMsg3Action(pAd, pEntry, Elem);
 294                                        else
 295                                                PeerGroupMsg1Action(pAd, pEntry, Elem);
 296                                }
 297                        }
 298                        else
 299                        {
 300                                // The frame is snet by Supplicant.
 301                                // So the Authenticator side shall handle this.
 302                                if ((peerKeyInfo.Request == 0) &&
 303                                                 (peerKeyInfo.Error == 0) &&
 304                                                 (peerKeyInfo.KeyMic == 1))
 305                                {
 306                                        if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY)
 307                                        {
 308                                                // EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data)
 309                                                // Process 1. message 2 of 4-way HS in WPA or WPA2
 310                                                //                 2. message 4 of 4-way HS in WPA
 311                                                if (CONV_ARRARY_TO_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0)
 312                                                {
 313                                                        PeerPairMsg4Action(pAd, pEntry, Elem);
 314                        }
 315                                                else
 316                                                {
 317                                                        PeerPairMsg2Action(pAd, pEntry, Elem);
 318                                                }
 319                                        }
 320                                        else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY)
 321                                        {
 322                                                // EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0)
 323                                                // Process message 4 of 4-way HS in WPA2
 324                                                PeerPairMsg4Action(pAd, pEntry, Elem);
 325                                        }
 326                                        else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY)
 327                                        {
 328                                                // EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0)
 329                                                // Process message 2 of Group key HS in WPA or WPA2
 330                                                PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11));
 331                                        }
 332                                }
 333                        }
 334        }
 335    }while(FALSE);
 336}
 337
 338/*
 339        ========================================================================
 340
 341        Routine Description:
 342                Copy frame from waiting queue into relative ring buffer and set
 343        appropriate ASIC register to kick hardware encryption before really
 344        sent out to air.
 345
 346        Arguments:
 347                pAd             Pointer to our adapter
 348                PNDIS_PACKET    Pointer to outgoing Ndis frame
 349                NumberOfFrag    Number of fragment required
 350
 351        Return Value:
 352                None
 353
 354        Note:
 355
 356        ========================================================================
 357*/
 358VOID    RTMPToWirelessSta(
 359    IN  PRTMP_ADAPTER           pAd,
 360    IN  PMAC_TABLE_ENTRY        pEntry,
 361    IN  PUCHAR                  pHeader802_3,
 362    IN  UINT                    HdrLen,
 363    IN  PUCHAR                  pData,
 364    IN  UINT                    DataLen,
 365    IN  BOOLEAN                         bClearFrame)
 366{
 367    PNDIS_PACKET    pPacket;
 368    NDIS_STATUS     Status;
 369
 370        if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
 371                return;
 372
 373    do {
 374                // build a NDIS packet
 375                Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
 376                if (Status != NDIS_STATUS_SUCCESS)
 377                break;
 378
 379
 380                        if (bClearFrame)
 381                                RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
 382                        else
 383                                RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
 384                {
 385                        RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
 386
 387                        RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID);        // set a default value
 388                        if(pEntry->apidx != 0)
 389                        RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx);
 390
 391                RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
 392                        RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
 393                }
 394
 395#ifdef CONFIG_STA_SUPPORT
 396                IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
 397                {
 398                    // send out the packet
 399                Status = STASendPacket(pAd, pPacket);
 400            if (Status == NDIS_STATUS_SUCCESS)
 401                        {
 402                                UCHAR   Index;
 403
 404                                // Dequeue one frame from TxSwQueue0..3 queue and process it
 405                                // There are three place calling dequeue for TX ring.
 406                                // 1. Here, right after queueing the frame.
 407                                // 2. At the end of TxRingTxDone service routine.
 408                                // 3. Upon NDIS call RTMPSendPackets
 409                                if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
 410                                        (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
 411                                {
 412                                        for(Index = 0; Index < 5; Index ++)
 413                                                if(pAd->TxSwQueue[Index].Number > 0)
 414                                                        RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS);
 415                                }
 416                        }
 417                }
 418#endif // CONFIG_STA_SUPPORT //
 419
 420    } while (FALSE);
 421}
 422
 423/*
 424    ==========================================================================
 425    Description:
 426        This is a function to initilize 4-way handshake
 427
 428    Return:
 429
 430    ==========================================================================
 431*/
 432VOID WPAStart4WayHS(
 433    IN PRTMP_ADAPTER    pAd,
 434    IN MAC_TABLE_ENTRY  *pEntry,
 435    IN ULONG                    TimeInterval)
 436{
 437    UCHAR           Header802_3[14];
 438    EAPOL_PACKET        EAPOLPKT;
 439        PUINT8                  pBssid = NULL;
 440        UCHAR                   group_cipher = Ndis802_11WEPDisabled;
 441
 442    DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
 443
 444        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
 445        {
 446                DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
 447                return;
 448        }
 449
 450
 451        if (pBssid == NULL)
 452        {
 453                DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
 454                return;
 455    }
 456
 457        // Check the status
 458    if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK))
 459    {
 460        DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
 461        return;
 462    }
 463
 464
 465        // Increment replay counter by 1
 466        ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
 467
 468        // Randomly generate ANonce
 469        GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce);
 470
 471        // Construct EAPoL message - Pairwise Msg 1
 472        // EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1)
 473        NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
 474        ConstructEapolMsg(pEntry,
 475                                          group_cipher,
 476                                          EAPOL_PAIR_MSG_1,
 477                                          0,                                    // Default key index
 478                                          pEntry->ANonce,
 479                                          NULL,                                 // TxRSC
 480                                          NULL,                                 // GTK
 481                                          NULL,                                 // RSNIE
 482                                          0,                                    // RSNIE length
 483                                          &EAPOLPKT);
 484
 485
 486        // Make outgoing frame
 487    MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
 488    RTMPToWirelessSta(pAd, pEntry, Header802_3,
 489                                          LENGTH_802_3, (PUCHAR)&EAPOLPKT,
 490                                          CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4,
 491                                          (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
 492
 493        // Trigger Retry Timer
 494    RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
 495
 496        // Update State
 497    pEntry->WpaState = AS_PTKSTART;
 498
 499        DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
 500
 501}
 502
 503/*
 504        ========================================================================
 505
 506        Routine Description:
 507                Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
 508
 509        Arguments:
 510                pAd                     Pointer to our adapter
 511                Elem            Message body
 512
 513        Return Value:
 514                None
 515
 516        Note:
 517
 518        ========================================================================
 519*/
 520VOID PeerPairMsg1Action(
 521        IN PRTMP_ADAPTER    pAd,
 522    IN MAC_TABLE_ENTRY  *pEntry,
 523    IN MLME_QUEUE_ELEM  *Elem)
 524{
 525        UCHAR                           PTK[80];
 526        UCHAR               Header802_3[14];
 527        PEAPOL_PACKET           pMsg1;
 528        UINT                    MsgLen;
 529        EAPOL_PACKET            EAPOLPKT;
 530        PUINT8                          pCurrentAddr = NULL;
 531        PUINT8                          pmk_ptr = NULL;
 532        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
 533        PUINT8                          rsnie_ptr = NULL;
 534        UCHAR                           rsnie_len = 0;
 535
 536        DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
 537
 538        if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
 539                return;
 540
 541    if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
 542        return;
 543
 544#ifdef CONFIG_STA_SUPPORT
 545        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
 546        {
 547                pCurrentAddr = pAd->CurrentAddress;
 548                pmk_ptr = pAd->StaCfg.PMK;
 549                group_cipher = pAd->StaCfg.GroupCipher;
 550                rsnie_ptr = pAd->StaCfg.RSN_IE;
 551                rsnie_len = pAd->StaCfg.RSNIE_Len;
 552        }
 553#endif // CONFIG_STA_SUPPORT //
 554
 555        // Store the received frame
 556        pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 557        MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
 558
 559        // Sanity Check peer Pairwise message 1 - Replay Counter
 560        if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE)
 561                return;
 562
 563        // Store Replay counter, it will use to verify message 3 and construct message 2
 564        NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
 565
 566        // Store ANonce
 567        NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
 568
 569        // Generate random SNonce
 570        GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce);
 571
 572        {
 573            // Calculate PTK(ANonce, SNonce)
 574            WpaDerivePTK(pAd,
 575                                pmk_ptr,
 576                                pEntry->ANonce,
 577                                        pEntry->Addr,
 578                                        pEntry->SNonce,
 579                                        pCurrentAddr,
 580                                    PTK,
 581                                    LEN_PTK);
 582
 583                // Save key to PTK entry
 584                NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
 585        }
 586
 587        // Update WpaState
 588        pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
 589
 590        // Construct EAPoL message - Pairwise Msg 2
 591        //  EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2)
 592        NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
 593        ConstructEapolMsg(pEntry,
 594                                          group_cipher,
 595                                          EAPOL_PAIR_MSG_2,
 596                                          0,                            // DefaultKeyIdx
 597                                          pEntry->SNonce,
 598                                          NULL,                         // TxRsc
 599                                          NULL,                         // GTK
 600                                          (UCHAR *)rsnie_ptr,
 601                                          rsnie_len,
 602                                          &EAPOLPKT);
 603
 604        // Make outgoing frame
 605        MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
 606
 607        RTMPToWirelessSta(pAd, pEntry,
 608                                          Header802_3, sizeof(Header802_3), (PUCHAR)&EAPOLPKT,
 609                                          CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE);
 610
 611        DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
 612}
 613
 614
 615/*
 616    ==========================================================================
 617    Description:
 618        When receiving the second packet of 4-way pairwisekey handshake.
 619    Return:
 620    ==========================================================================
 621*/
 622VOID PeerPairMsg2Action(
 623    IN PRTMP_ADAPTER    pAd,
 624    IN MAC_TABLE_ENTRY  *pEntry,
 625    IN MLME_QUEUE_ELEM  *Elem)
 626{
 627        UCHAR                           PTK[80];
 628    BOOLEAN             Cancelled;
 629    PHEADER_802_11      pHeader;
 630        EAPOL_PACKET        EAPOLPKT;
 631        PEAPOL_PACKET       pMsg2;
 632        UINT                    MsgLen;
 633    UCHAR               Header802_3[LENGTH_802_3];
 634        UCHAR                           TxTsc[6];
 635        PUINT8                          pBssid = NULL;
 636        PUINT8                          pmk_ptr = NULL;
 637        PUINT8                          gtk_ptr = NULL;
 638        UCHAR                           default_key = 0;
 639        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
 640        PUINT8                          rsnie_ptr = NULL;
 641        UCHAR                           rsnie_len = 0;
 642
 643    DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
 644
 645    if ((!pEntry) || (!pEntry->ValidAsCLI))
 646        return;
 647
 648    if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
 649        return;
 650
 651    // check Entry in valid State
 652    if (pEntry->WpaState < AS_PTKSTART)
 653        return;
 654
 655
 656
 657    // pointer to 802.11 header
 658        pHeader = (PHEADER_802_11)Elem->Msg;
 659
 660        // skip 802.11_header(24-byte) and LLC_header(8)
 661        pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 662        MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
 663
 664        // Store SNonce
 665        NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
 666
 667        {
 668                // Derive PTK
 669                WpaDerivePTK(pAd,
 670                                        (UCHAR *)pmk_ptr,
 671                                        pEntry->ANonce,                 // ANONCE
 672                                        (UCHAR *)pBssid,
 673                                        pEntry->SNonce,                 // SNONCE
 674                                        pEntry->Addr,
 675                                        PTK,
 676                                        LEN_PTK);
 677
 678        NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
 679        }
 680
 681        // Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE
 682        if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE)
 683                return;
 684
 685    do
 686    {
 687        // delete retry timer
 688                RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
 689
 690                // Change state
 691        pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
 692
 693                // Increment replay counter by 1
 694                ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
 695
 696                // Construct EAPoL message - Pairwise Msg 3
 697                NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
 698                ConstructEapolMsg(pEntry,
 699                                                  group_cipher,
 700                                                  EAPOL_PAIR_MSG_3,
 701                                                  default_key,
 702                                                  pEntry->ANonce,
 703                                                  TxTsc,
 704                                                  (UCHAR *)gtk_ptr,
 705                                                  (UCHAR *)rsnie_ptr,
 706                                                  rsnie_len,
 707                                                  &EAPOLPKT);
 708
 709        // Make outgoing frame
 710        MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
 711        RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
 712                                                  (PUCHAR)&EAPOLPKT,
 713                                                  CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4,
 714                                                  (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
 715
 716        pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
 717                RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
 718
 719                // Update State
 720        pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
 721    }while(FALSE);
 722
 723        DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
 724}
 725
 726/*
 727        ========================================================================
 728
 729        Routine Description:
 730                Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
 731
 732        Arguments:
 733                pAd     Pointer to our adapter
 734                Elem            Message body
 735
 736        Return Value:
 737                None
 738
 739        Note:
 740
 741        ========================================================================
 742*/
 743VOID PeerPairMsg3Action(
 744    IN PRTMP_ADAPTER    pAd,
 745    IN MAC_TABLE_ENTRY  *pEntry,
 746    IN MLME_QUEUE_ELEM  *Elem)
 747{
 748        PHEADER_802_11          pHeader;
 749        UCHAR               Header802_3[14];
 750        EAPOL_PACKET            EAPOLPKT;
 751        PEAPOL_PACKET           pMsg3;
 752        UINT                    MsgLen;
 753        PUINT8                          pCurrentAddr = NULL;
 754        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
 755
 756        DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
 757
 758        if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
 759                return;
 760
 761    if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
 762                return;
 763
 764#ifdef CONFIG_STA_SUPPORT
 765        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
 766        {
 767                pCurrentAddr = pAd->CurrentAddress;
 768                group_cipher = pAd->StaCfg.GroupCipher;
 769
 770        }
 771#endif // CONFIG_STA_SUPPORT //
 772
 773        // Record 802.11 header & the received EAPOL packet Msg3
 774        pHeader = (PHEADER_802_11) Elem->Msg;
 775        pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 776        MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
 777
 778        // Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE
 779        if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE)
 780                return;
 781
 782        // Save Replay counter, it will use construct message 4
 783        NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
 784
 785        // Double check ANonce
 786        if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
 787        {
 788                return;
 789        }
 790
 791        // Construct EAPoL message - Pairwise Msg 4
 792        NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
 793        ConstructEapolMsg(pEntry,
 794                                          group_cipher,
 795                                          EAPOL_PAIR_MSG_4,
 796                                          0,                                    // group key index not used in message 4
 797                                          NULL,                                 // Nonce not used in message 4
 798                                          NULL,                                 // TxRSC not used in message 4
 799                                          NULL,                                 // GTK not used in message 4
 800                                          NULL,                                 // RSN IE not used in message 4
 801                                          0,
 802                                          &EAPOLPKT);
 803
 804        // Update WpaState
 805        pEntry->WpaState = AS_PTKINITDONE;
 806
 807        // Update pairwise key
 808#ifdef CONFIG_STA_SUPPORT
 809        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
 810        {
 811                PCIPHER_KEY pSharedKey;
 812
 813                pSharedKey = &pAd->SharedKey[BSS0][0];
 814
 815                NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
 816
 817                // Prepare pair-wise key information into shared key table
 818                NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
 819                pSharedKey->KeyLen = LEN_TKIP_EK;
 820            NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
 821                NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
 822                NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
 823
 824                // Decide its ChiperAlg
 825                if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
 826                        pSharedKey->CipherAlg = CIPHER_TKIP;
 827                else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
 828                        pSharedKey->CipherAlg = CIPHER_AES;
 829                else
 830                        pSharedKey->CipherAlg = CIPHER_NONE;
 831
 832                // Update these related information to MAC_TABLE_ENTRY
 833                pEntry = &pAd->MacTab.Content[BSSID_WCID];
 834                NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
 835                NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
 836                NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
 837                pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
 838
 839                // Update pairwise key information to ASIC Shared Key Table
 840                AsicAddSharedKeyEntry(pAd,
 841                                                          BSS0,
 842                                                          0,
 843                                                          pSharedKey->CipherAlg,
 844                                                          pSharedKey->Key,
 845                                                          pSharedKey->TxMic,
 846                                                          pSharedKey->RxMic);
 847
 848                // Update ASIC WCID attribute table and IVEIV table
 849                RTMPAddWcidAttributeEntry(pAd,
 850                                                                  BSS0,
 851                                                                  0,
 852                                                                  pSharedKey->CipherAlg,
 853                                                                  pEntry);
 854
 855        }
 856#endif // CONFIG_STA_SUPPORT //
 857
 858        // open 802.1x port control and privacy filter
 859        if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
 860                pEntry->AuthMode == Ndis802_11AuthModeWPA2)
 861        {
 862                pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
 863                pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
 864
 865#ifdef CONFIG_STA_SUPPORT
 866                STA_PORT_SECURED(pAd);
 867            // Indicate Connected for GUI
 868            pAd->IndicateMediaState = NdisMediaStateConnected;
 869#endif // CONFIG_STA_SUPPORT //
 870                DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
 871                                                                        GetAuthMode(pEntry->AuthMode),
 872                                                                        GetEncryptType(pEntry->WepStatus),
 873                                                                        GetEncryptType(group_cipher)));
 874        }
 875        else
 876        {
 877        }
 878
 879        // Init 802.3 header and send out
 880        MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
 881        RTMPToWirelessSta(pAd, pEntry,
 882                                          Header802_3, sizeof(Header802_3),
 883                                          (PUCHAR)&EAPOLPKT,
 884                                          CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE);
 885
 886        DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
 887}
 888
 889/*
 890    ==========================================================================
 891    Description:
 892        When receiving the last packet of 4-way pairwisekey handshake.
 893        Initilize 2-way groupkey handshake following.
 894    Return:
 895    ==========================================================================
 896*/
 897VOID PeerPairMsg4Action(
 898    IN PRTMP_ADAPTER    pAd,
 899    IN MAC_TABLE_ENTRY  *pEntry,
 900    IN MLME_QUEUE_ELEM  *Elem)
 901{
 902        PEAPOL_PACKET           pMsg4;
 903    PHEADER_802_11      pHeader;
 904    UINT                MsgLen;
 905    BOOLEAN             Cancelled;
 906        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
 907
 908    DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
 909
 910    do
 911    {
 912        if ((!pEntry) || (!pEntry->ValidAsCLI))
 913            break;
 914
 915        if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2 ) )
 916            break;
 917
 918        if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
 919            break;
 920
 921
 922        // pointer to 802.11 header
 923        pHeader = (PHEADER_802_11)Elem->Msg;
 924
 925                // skip 802.11_header(24-byte) and LLC_header(8)
 926                pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 927                MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
 928
 929        // Sanity Check peer Pairwise message 4 - Replay Counter, MIC
 930                if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
 931                        break;
 932
 933        // 3. uses the MLME.SETKEYS.request to configure PTK into MAC
 934        NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
 935
 936                // reset IVEIV in Asic
 937                AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
 938
 939        pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK;
 940        NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32], LEN_TKIP_EK);
 941        NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[TKIP_AP_RXMICK_OFFSET], LEN_TKIP_RXMICK);
 942        NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[TKIP_AP_TXMICK_OFFSET], LEN_TKIP_TXMICK);
 943
 944                // Set pairwise key to Asic
 945        {
 946            pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
 947            if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
 948                pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
 949            else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
 950                pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
 951
 952                        // Add Pair-wise key to Asic
 953            AsicAddPairwiseKeyEntry(
 954                pAd,
 955                pEntry->Addr,
 956                (UCHAR)pEntry->Aid,
 957                &pEntry->PairwiseKey);
 958
 959                        // update WCID attribute table and IVEIV table for this entry
 960                        RTMPAddWcidAttributeEntry(
 961                                pAd,
 962                                pEntry->apidx,
 963                                0,
 964                                pEntry->PairwiseKey.CipherAlg,
 965                                pEntry);
 966        }
 967
 968        // 4. upgrade state
 969        pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
 970        pEntry->WpaState = AS_PTKINITDONE;
 971                pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
 972
 973
 974                if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
 975                        pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
 976                {
 977                        pEntry->GTKState = REKEY_ESTABLISHED;
 978                        RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
 979
 980
 981                        // send wireless event - for set key done WPA2
 982                        if (pAd->CommonCfg.bWirelessEvent)
 983                                RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
 984
 985                DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
 986                                                                        pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
 987                                                                        pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
 988                                                                        group_cipher,
 989                                                                        GetEncryptType(group_cipher)));
 990                }
 991                else
 992                {
 993                // 5. init Group 2-way handshake if necessary.
 994                WPAStart2WayGroupHS(pAd, pEntry);
 995
 996                pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
 997                        RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
 998                }
 999    }while(FALSE);
1000
1001}
1002
1003/*
1004    ==========================================================================
1005    Description:
1006        This is a function to send the first packet of 2-way groupkey handshake
1007    Return:
1008
1009    ==========================================================================
1010*/
1011VOID WPAStart2WayGroupHS(
1012    IN PRTMP_ADAPTER    pAd,
1013    IN MAC_TABLE_ENTRY  *pEntry)
1014{
1015    UCHAR               Header802_3[14];
1016        UCHAR                           TxTsc[6];
1017    EAPOL_PACKET        EAPOLPKT;
1018        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
1019        UCHAR                           default_key = 0;
1020        PUINT8                          gnonce_ptr = NULL;
1021        PUINT8                          gtk_ptr = NULL;
1022        PUINT8                          pBssid = NULL;
1023
1024        DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1025
1026    if ((!pEntry) || (!pEntry->ValidAsCLI))
1027        return;
1028
1029
1030    do
1031    {
1032        // Increment replay counter by 1
1033                ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1034
1035                // Construct EAPoL message - Group Msg 1
1036                NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
1037                ConstructEapolMsg(pEntry,
1038                                                  group_cipher,
1039                                                  EAPOL_GROUP_MSG_1,
1040                                                  default_key,
1041                                                  (UCHAR *)gnonce_ptr,
1042                                                  TxTsc,
1043                                                  (UCHAR *)gtk_ptr,
1044                                                  NULL,
1045                                                  0,
1046                                                  &EAPOLPKT);
1047
1048                // Make outgoing frame
1049        MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
1050        RTMPToWirelessSta(pAd, pEntry,
1051                                                  Header802_3, LENGTH_802_3,
1052                                                  (PUCHAR)&EAPOLPKT,
1053                                                  CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE);
1054
1055
1056
1057    }while (FALSE);
1058
1059    DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
1060
1061    return;
1062}
1063
1064/*
1065        ========================================================================
1066
1067        Routine Description:
1068                Process Group key 2-way handshaking
1069
1070        Arguments:
1071                pAd     Pointer to our adapter
1072                Elem            Message body
1073
1074        Return Value:
1075                None
1076
1077        Note:
1078
1079        ========================================================================
1080*/
1081VOID    PeerGroupMsg1Action(
1082        IN PRTMP_ADAPTER    pAd,
1083    IN MAC_TABLE_ENTRY  *pEntry,
1084    IN MLME_QUEUE_ELEM  *Elem)
1085{
1086    UCHAR               Header802_3[14];
1087        EAPOL_PACKET            EAPOLPKT;
1088        PEAPOL_PACKET           pGroup;
1089        UINT                    MsgLen;
1090        BOOLEAN             Cancelled;
1091        UCHAR                           default_key = 0;
1092        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
1093        PUINT8                          pCurrentAddr = NULL;
1094
1095        DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1096
1097        if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
1098        return;
1099
1100#ifdef CONFIG_STA_SUPPORT
1101        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1102        {
1103                pCurrentAddr = pAd->CurrentAddress;
1104                group_cipher = pAd->StaCfg.GroupCipher;
1105                default_key = pAd->StaCfg.DefaultKeyId;
1106        }
1107#endif // CONFIG_STA_SUPPORT //
1108
1109        // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)
1110        pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1111        MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
1112
1113        // Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE
1114        if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) == FALSE)
1115                return;
1116
1117        // delete retry timer
1118        RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1119
1120        // Save Replay counter, it will use to construct message 2
1121        NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1122
1123        // Construct EAPoL message - Group Msg 2
1124        NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
1125        ConstructEapolMsg(pEntry,
1126                                          group_cipher,
1127                                          EAPOL_GROUP_MSG_2,
1128                                          default_key,
1129                                          NULL,                                 // Nonce not used
1130                                          NULL,                                 // TxRSC not used
1131                                          NULL,                                 // GTK not used
1132                                          NULL,                                 // RSN IE not used
1133                                          0,
1134                                          &EAPOLPKT);
1135
1136    // open 802.1x port control and privacy filter
1137        pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1138        pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1139
1140#ifdef CONFIG_STA_SUPPORT
1141        STA_PORT_SECURED(pAd);
1142    // Indicate Connected for GUI
1143    pAd->IndicateMediaState = NdisMediaStateConnected;
1144#endif // CONFIG_STA_SUPPORT //
1145
1146        DBGPRINT(RT_DEBUG_TRACE, ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
1147                                                                        GetAuthMode(pEntry->AuthMode),
1148                                                                        GetEncryptType(pEntry->WepStatus),
1149                                                                        GetEncryptType(group_cipher)));
1150
1151        // init header and Fill Packet and send Msg 2 to authenticator
1152        MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
1153        RTMPToWirelessSta(pAd, pEntry,
1154                                          Header802_3, sizeof(Header802_3),
1155                                          (PUCHAR)&EAPOLPKT,
1156                                          CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE);
1157
1158        DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: sned group message 2\n"));
1159}
1160
1161/*
1162    ==========================================================================
1163    Description:
1164        When receiving the last packet of 2-way groupkey handshake.
1165    Return:
1166    ==========================================================================
1167*/
1168VOID PeerGroupMsg2Action(
1169    IN PRTMP_ADAPTER    pAd,
1170    IN MAC_TABLE_ENTRY  *pEntry,
1171    IN VOID             *Msg,
1172    IN UINT             MsgLen)
1173{
1174    UINT                Len;
1175    PUCHAR              pData;
1176    BOOLEAN             Cancelled;
1177        PEAPOL_PACKET       pMsg2;
1178        UCHAR                           group_cipher = Ndis802_11WEPDisabled;
1179
1180        DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1181
1182    do
1183    {
1184        if ((!pEntry) || (!pEntry->ValidAsCLI))
1185            break;
1186
1187        if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
1188            break;
1189
1190        if (pEntry->WpaState != AS_PTKINITDONE)
1191            break;
1192
1193
1194        pData = (PUCHAR)Msg;
1195                pMsg2 = (PEAPOL_PACKET) (pData + LENGTH_802_1_H);
1196        Len = MsgLen - LENGTH_802_1_H;
1197
1198                // Sanity Check peer group message 2 - Replay Counter, MIC
1199                if (PeerWpaMessageSanity(pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1200            break;
1201
1202        // 3.  upgrade state
1203
1204                RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1205        pEntry->GTKState = REKEY_ESTABLISHED;
1206
1207                if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
1208                {
1209                        // send wireless event - for set key done WPA2
1210                        if (pAd->CommonCfg.bWirelessEvent)
1211                                RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1212
1213                        DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1214                                                                                pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
1215                                                                                pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
1216                                                                                group_cipher, GetEncryptType(group_cipher)));
1217                }
1218                else
1219                {
1220                        // send wireless event - for set key done WPA
1221                        if (pAd->CommonCfg.bWirelessEvent)
1222                                RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA1_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1223
1224                DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1225                                                                                pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
1226                                                                                pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
1227                                                                                group_cipher, GetEncryptType(group_cipher)));
1228                }
1229    }while(FALSE);
1230}
1231
1232/*
1233        ========================================================================
1234
1235        Routine Description:
1236                Classify WPA EAP message type
1237
1238        Arguments:
1239                EAPType         Value of EAP message type
1240                MsgType         Internal Message definition for MLME state machine
1241
1242        Return Value:
1243                TRUE            Found appropriate message type
1244                FALSE           No appropriate message type
1245
1246        IRQL = DISPATCH_LEVEL
1247
1248        Note:
1249                All these constants are defined in wpa.h
1250                For supplicant, there is only EAPOL Key message avaliable
1251
1252        ========================================================================
1253*/
1254BOOLEAN WpaMsgTypeSubst(
1255        IN      UCHAR   EAPType,
1256        OUT     INT             *MsgType)
1257{
1258        switch (EAPType)
1259        {
1260                case EAPPacket:
1261                        *MsgType = MT2_EAPPacket;
1262                        break;
1263                case EAPOLStart:
1264                        *MsgType = MT2_EAPOLStart;
1265                        break;
1266                case EAPOLLogoff:
1267                        *MsgType = MT2_EAPOLLogoff;
1268                        break;
1269                case EAPOLKey:
1270                        *MsgType = MT2_EAPOLKey;
1271                        break;
1272                case EAPOLASFAlert:
1273                        *MsgType = MT2_EAPOLASFAlert;
1274                        break;
1275                default:
1276                        return FALSE;
1277        }
1278        return TRUE;
1279}
1280
1281/*
1282        ========================================================================
1283
1284        Routine Description:
1285                The pseudo-random function(PRF) that hashes various inputs to
1286                derive a pseudo-random value. To add liveness to the pseudo-random
1287                value, a nonce should be one of the inputs.
1288
1289                It is used to generate PTK, GTK or some specific random value.
1290
1291        Arguments:
1292                UCHAR   *key,           -       the key material for HMAC_SHA1 use
1293                INT             key_len         -       the length of key
1294                UCHAR   *prefix         -       a prefix label
1295                INT             prefix_len      -       the length of the label
1296                UCHAR   *data           -       a specific data with variable length
1297                INT             data_len        -       the length of a specific data
1298                INT             len                     -       the output lenght
1299
1300        Return Value:
1301                UCHAR   *output         -       the calculated result
1302
1303        Note:
1304                802.11i-2004    Annex H.3
1305
1306        ========================================================================
1307*/
1308VOID    PRF(
1309        IN      UCHAR   *key,
1310        IN      INT             key_len,
1311        IN      UCHAR   *prefix,
1312        IN      INT             prefix_len,
1313        IN      UCHAR   *data,
1314        IN      INT             data_len,
1315        OUT     UCHAR   *output,
1316        IN      INT             len)
1317{
1318        INT             i;
1319    UCHAR   *input;
1320        INT             currentindex = 0;
1321        INT             total_len;
1322
1323        // Allocate memory for input
1324        os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
1325
1326    if (input == NULL)
1327    {
1328        DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
1329        return;
1330    }
1331
1332        // Generate concatenation input
1333        NdisMoveMemory(input, prefix, prefix_len);
1334
1335        // Concatenate a single octet containing 0
1336        input[prefix_len] =     0;
1337
1338        // Concatenate specific data
1339        NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1340        total_len =     prefix_len + 1 + data_len;
1341
1342        // Concatenate a single octet containing 0
1343        // This octet shall be update later
1344        input[total_len] = 0;
1345        total_len++;
1346
1347        // Iterate to calculate the result by hmac-sha-1
1348        // Then concatenate to last result
1349        for     (i = 0; i <     (len + 19) / 20; i++)
1350        {
1351                HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], SHA1_DIGEST_SIZE);
1352                currentindex += 20;
1353
1354                // update the last octet
1355                input[total_len - 1]++;
1356        }
1357    os_free_mem(NULL, input);
1358}
1359
1360/*
1361* F(P, S, c, i) = U1 xor U2 xor ... Uc
1362* U1 = PRF(P, S || Int(i))
1363* U2 = PRF(P, U1)
1364* Uc = PRF(P, Uc-1)
1365*/
1366
1367static void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output)
1368{
1369    unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
1370    int i, j;
1371
1372    /* U1 = PRF(P, S || int(i)) */
1373    memcpy(digest, ssid, ssidlength);
1374    digest[ssidlength] = (unsigned char)((count>>24) & 0xff);
1375    digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff);
1376    digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff);
1377    digest[ssidlength+3] = (unsigned char)(count & 0xff);
1378    HMAC_SHA1((unsigned char*) password, (int) strlen(password), digest, ssidlength+4, digest1, SHA1_DIGEST_SIZE); // for WPA update
1379
1380    /* output = U1 */
1381    memcpy(output, digest1, SHA1_DIGEST_SIZE);
1382
1383    for (i = 1; i < iterations; i++)
1384    {
1385        /* Un = PRF(P, Un-1) */
1386        HMAC_SHA1((unsigned char*) password, (int) strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); // for WPA update
1387        memcpy(digest1, digest, SHA1_DIGEST_SIZE);
1388
1389        /* output = output xor Un */
1390        for (j = 0; j < SHA1_DIGEST_SIZE; j++)
1391        {
1392            output[j] ^= digest[j];
1393        }
1394    }
1395}
1396
1397/*
1398* password - ascii string up to 63 characters in length
1399* ssid - octet string up to 32 octets
1400* ssidlength - length of ssid in octets
1401* output must be 40 octets in length and outputs 256 bits of key
1402*/
1403int PasswordHash(PSTRING password, PUCHAR ssid, INT ssidlength, PUCHAR output)
1404{
1405    if ((strlen(password) > 63) || (ssidlength > 32))
1406        return 0;
1407
1408    F(password, ssid, ssidlength, 4096, 1, output);
1409    F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1410    return 1;
1411}
1412
1413
1414
1415/*
1416        ========================================================================
1417
1418        Routine Description:
1419                It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
1420                It shall be called by 4-way handshake processing.
1421
1422        Arguments:
1423                pAd     -       pointer to our pAdapter context
1424                PMK             -       pointer to PMK
1425                ANonce  -       pointer to ANonce
1426                AA              -       pointer to Authenticator Address
1427                SNonce  -       pointer to SNonce
1428                SA              -       pointer to Supplicant Address
1429                len             -       indicate the length of PTK (octet)
1430
1431        Return Value:
1432                Output          pointer to the PTK
1433
1434        Note:
1435                Refer to IEEE 802.11i-2004 8.5.1.2
1436
1437        ========================================================================
1438*/
1439VOID WpaDerivePTK(
1440        IN      PRTMP_ADAPTER   pAd,
1441        IN      UCHAR   *PMK,
1442        IN      UCHAR   *ANonce,
1443        IN      UCHAR   *AA,
1444        IN      UCHAR   *SNonce,
1445        IN      UCHAR   *SA,
1446        OUT     UCHAR   *output,
1447        IN      UINT    len)
1448{
1449        UCHAR   concatenation[76];
1450        UINT    CurrPos = 0;
1451        UCHAR   temp[32];
1452        UCHAR   Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1453                                                'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
1454
1455        // initiate the concatenation input
1456        NdisZeroMemory(temp, sizeof(temp));
1457        NdisZeroMemory(concatenation, 76);
1458
1459        // Get smaller address
1460        if (RTMPCompareMemory(SA, AA, 6) == 1)
1461                NdisMoveMemory(concatenation, AA, 6);
1462        else
1463                NdisMoveMemory(concatenation, SA, 6);
1464        CurrPos += 6;
1465
1466        // Get larger address
1467        if (RTMPCompareMemory(SA, AA, 6) == 1)
1468                NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1469        else
1470                NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1471
1472        // store the larger mac address for backward compatible of
1473        // ralink proprietary STA-key issue
1474        NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
1475        CurrPos += 6;
1476
1477        // Get smaller Nonce
1478        if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1479                NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
1480        else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1481                NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1482        else
1483                NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1484        CurrPos += 32;
1485
1486        // Get larger Nonce
1487        if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1488                NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
1489        else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1490                NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1491        else
1492                NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1493        CurrPos += 32;
1494
1495        hex_dump("concatenation=", concatenation, 76);
1496
1497        // Use PRF to generate PTK
1498        PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
1499
1500}
1501
1502/*
1503        ========================================================================
1504
1505        Routine Description:
1506                Generate random number by software.
1507
1508        Arguments:
1509                pAd             -       pointer to our pAdapter context
1510                macAddr -       pointer to local MAC address
1511
1512        Return Value:
1513
1514        Note:
1515                802.1ii-2004  Annex H.5
1516
1517        ========================================================================
1518*/
1519VOID    GenRandom(
1520        IN      PRTMP_ADAPTER   pAd,
1521        IN      UCHAR                   *macAddr,
1522        OUT     UCHAR                   *random)
1523{
1524        INT             i, curr;
1525        UCHAR   local[80], KeyCounter[32];
1526        UCHAR   result[80];
1527        ULONG   CurrentTime;
1528        UCHAR   prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
1529
1530        // Zero the related information
1531        NdisZeroMemory(result, 80);
1532        NdisZeroMemory(local, 80);
1533        NdisZeroMemory(KeyCounter, 32);
1534
1535        for     (i = 0; i <     32;     i++)
1536        {
1537                // copy the local MAC address
1538                COPY_MAC_ADDR(local, macAddr);
1539                curr =  MAC_ADDR_LEN;
1540
1541                // concatenate the current time
1542                NdisGetSystemUpTime(&CurrentTime);
1543                NdisMoveMemory(&local[curr],  &CurrentTime,     sizeof(CurrentTime));
1544                curr += sizeof(CurrentTime);
1545
1546                // concatenate the last result
1547                NdisMoveMemory(&local[curr],  result, 32);
1548                curr += 32;
1549
1550                // concatenate a variable
1551                NdisMoveMemory(&local[curr],  &i,  2);
1552                curr += 2;
1553
1554                // calculate the result
1555                PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
1556        }
1557
1558        NdisMoveMemory(random, result,  32);
1559}
1560
1561/*
1562        ========================================================================
1563
1564        Routine Description:
1565                Build cipher suite in RSN-IE.
1566                It only shall be called by RTMPMakeRSNIE.
1567
1568        Arguments:
1569                pAd                     -       pointer to our pAdapter context
1570        ElementID       -       indicate the WPA1 or WPA2
1571        WepStatus       -       indicate the encryption type
1572                bMixCipher      -       a boolean to indicate the pairwise cipher and group
1573                                                cipher are the same or not
1574
1575        Return Value:
1576
1577        Note:
1578
1579        ========================================================================
1580*/
1581static VOID RTMPMakeRsnIeCipher(
1582        IN  PRTMP_ADAPTER   pAd,
1583        IN      UCHAR                   ElementID,
1584        IN      UINT                    WepStatus,
1585        IN      BOOLEAN                 bMixCipher,
1586        IN      UCHAR                   FlexibleCipher,
1587        OUT     PUCHAR                  pRsnIe,
1588        OUT     UCHAR                   *rsn_len)
1589{
1590        UCHAR   PairwiseCnt;
1591
1592        *rsn_len = 0;
1593
1594        // decide WPA2 or WPA1
1595        if (ElementID == Wpa2Ie)
1596        {
1597                RSNIE2  *pRsnie_cipher = (RSNIE2*)pRsnIe;
1598
1599                // Assign the verson as 1
1600                pRsnie_cipher->version = 1;
1601
1602        switch (WepStatus)
1603        {
1604                // TKIP mode
1605            case Ndis802_11Encryption2Enabled:
1606                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1607                pRsnie_cipher->ucount = 1;
1608                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
1609                *rsn_len = sizeof(RSNIE2);
1610                break;
1611
1612                        // AES mode
1613            case Ndis802_11Encryption3Enabled:
1614                                if (bMixCipher)
1615                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1616                                else
1617                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
1618                pRsnie_cipher->ucount = 1;
1619                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
1620                *rsn_len = sizeof(RSNIE2);
1621                break;
1622
1623                        // TKIP-AES mix mode
1624            case Ndis802_11Encryption4Enabled:
1625                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1626
1627                                PairwiseCnt = 1;
1628                                // Insert WPA2 TKIP as the first pairwise cipher
1629                                if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
1630                                {
1631                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
1632                                        // Insert WPA2 AES as the secondary pairwise cipher
1633                                        if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
1634                                        {
1635                                NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
1636                                                PairwiseCnt = 2;
1637                                        }
1638                                }
1639                                else
1640                                {
1641                                        // Insert WPA2 AES as the first pairwise cipher
1642                                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
1643                                }
1644
1645                pRsnie_cipher->ucount = PairwiseCnt;
1646                *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
1647                break;
1648        }
1649
1650#ifdef CONFIG_STA_SUPPORT
1651                if ((pAd->OpMode == OPMODE_STA) &&
1652                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1653                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
1654                {
1655                        UINT    GroupCipher = pAd->StaCfg.GroupCipher;
1656                        switch(GroupCipher)
1657                        {
1658                                case Ndis802_11GroupWEP40Enabled:
1659                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
1660                                        break;
1661                                case Ndis802_11GroupWEP104Enabled:
1662                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
1663                                        break;
1664                        }
1665                }
1666#endif // CONFIG_STA_SUPPORT //
1667
1668                // swap for big-endian platform
1669                pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1670            pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1671        }
1672        else
1673        {
1674                RSNIE   *pRsnie_cipher = (RSNIE*)pRsnIe;
1675
1676                // Assign OUI and version
1677                NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
1678        pRsnie_cipher->version = 1;
1679
1680                switch (WepStatus)
1681                {
1682                        // TKIP mode
1683            case Ndis802_11Encryption2Enabled:
1684                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1685                pRsnie_cipher->ucount = 1;
1686                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
1687                *rsn_len = sizeof(RSNIE);
1688                break;
1689
1690                        // AES mode
1691            case Ndis802_11Encryption3Enabled:
1692                                if (bMixCipher)
1693                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1694                                else
1695                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
1696                pRsnie_cipher->ucount = 1;
1697                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
1698                *rsn_len = sizeof(RSNIE);
1699                break;
1700
1701                        // TKIP-AES mix mode
1702            case Ndis802_11Encryption4Enabled:
1703                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1704
1705                                PairwiseCnt = 1;
1706                                // Insert WPA TKIP as the first pairwise cipher
1707                                if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
1708                                {
1709                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
1710                                        // Insert WPA AES as the secondary pairwise cipher
1711                                        if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
1712                                        {
1713                                NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
1714                                                PairwiseCnt = 2;
1715                                        }
1716                                }
1717                                else
1718                                {
1719                                        // Insert WPA AES as the first pairwise cipher
1720                                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
1721                                }
1722
1723                pRsnie_cipher->ucount = PairwiseCnt;
1724                *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
1725                break;
1726        }
1727
1728#ifdef CONFIG_STA_SUPPORT
1729                if ((pAd->OpMode == OPMODE_STA) &&
1730                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1731                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
1732                {
1733                        UINT    GroupCipher = pAd->StaCfg.GroupCipher;
1734                        switch(GroupCipher)
1735                        {
1736                                case Ndis802_11GroupWEP40Enabled:
1737                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
1738                                        break;
1739                                case Ndis802_11GroupWEP104Enabled:
1740                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
1741                                        break;
1742                        }
1743                }
1744#endif // CONFIG_STA_SUPPORT //
1745
1746                // swap for big-endian platform
1747                pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1748            pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1749        }
1750}
1751
1752/*
1753        ========================================================================
1754
1755        Routine Description:
1756                Build AKM suite in RSN-IE.
1757                It only shall be called by RTMPMakeRSNIE.
1758
1759        Arguments:
1760                pAd                     -       pointer to our pAdapter context
1761        ElementID       -       indicate the WPA1 or WPA2
1762        AuthMode        -       indicate the authentication mode
1763                apidx           -       indicate the interface index
1764
1765        Return Value:
1766
1767        Note:
1768
1769        ========================================================================
1770*/
1771static VOID RTMPMakeRsnIeAKM(
1772        IN  PRTMP_ADAPTER   pAd,
1773        IN      UCHAR                   ElementID,
1774        IN      UINT                    AuthMode,
1775        IN      UCHAR                   apidx,
1776        OUT     PUCHAR                  pRsnIe,
1777        OUT     UCHAR                   *rsn_len)
1778{
1779        RSNIE_AUTH              *pRsnie_auth;
1780        UCHAR                   AkmCnt = 1;             // default as 1
1781
1782        pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
1783
1784        // decide WPA2 or WPA1
1785        if (ElementID == Wpa2Ie)
1786        {
1787
1788                switch (AuthMode)
1789        {
1790            case Ndis802_11AuthModeWPA2:
1791            case Ndis802_11AuthModeWPA1WPA2:
1792                        NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
1793                break;
1794
1795            case Ndis802_11AuthModeWPA2PSK:
1796            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1797                        NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
1798                break;
1799                        default:
1800                                AkmCnt = 0;
1801                                break;
1802
1803        }
1804        }
1805        else
1806        {
1807                switch (AuthMode)
1808        {
1809            case Ndis802_11AuthModeWPA:
1810            case Ndis802_11AuthModeWPA1WPA2:
1811                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
1812                break;
1813
1814            case Ndis802_11AuthModeWPAPSK:
1815            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1816                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
1817                break;
1818
1819                        case Ndis802_11AuthModeWPANone:
1820                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
1821                break;
1822                        default:
1823                                AkmCnt = 0;
1824                                break;
1825        }
1826        }
1827
1828        pRsnie_auth->acount = AkmCnt;
1829        pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1830
1831        // update current RSNIE length
1832        (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1)));
1833
1834}
1835
1836/*
1837        ========================================================================
1838
1839        Routine Description:
1840                Build capability in RSN-IE.
1841                It only shall be called by RTMPMakeRSNIE.
1842
1843        Arguments:
1844                pAd                     -       pointer to our pAdapter context
1845        ElementID       -       indicate the WPA1 or WPA2
1846                apidx           -       indicate the interface index
1847
1848        Return Value:
1849
1850        Note:
1851
1852        ========================================================================
1853*/
1854static VOID RTMPMakeRsnIeCap(
1855        IN  PRTMP_ADAPTER   pAd,
1856        IN      UCHAR                   ElementID,
1857        IN      UCHAR                   apidx,
1858        OUT     PUCHAR                  pRsnIe,
1859        OUT     UCHAR                   *rsn_len)
1860{
1861        RSN_CAPABILITIES    *pRSN_Cap;
1862
1863        // it could be ignored in WPA1 mode
1864        if (ElementID == WpaIe)
1865                return;
1866
1867        pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
1868
1869
1870        pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1871
1872        (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
1873
1874}
1875
1876
1877/*
1878        ========================================================================
1879
1880        Routine Description:
1881                Build RSN IE context. It is not included element-ID and length.
1882
1883        Arguments:
1884                pAd                     -       pointer to our pAdapter context
1885        AuthMode        -       indicate the authentication mode
1886        WepStatus       -       indicate the encryption type
1887                apidx           -       indicate the interface index
1888
1889        Return Value:
1890
1891        Note:
1892
1893        ========================================================================
1894*/
1895VOID RTMPMakeRSNIE(
1896    IN  PRTMP_ADAPTER   pAd,
1897    IN  UINT            AuthMode,
1898    IN  UINT            WepStatus,
1899        IN      UCHAR                   apidx)
1900{
1901        PUCHAR          pRsnIe = NULL;                  // primary RSNIE
1902        UCHAR           *rsnielen_cur_p = 0;    // the length of the primary RSNIE
1903        UCHAR           *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
1904        UCHAR           PrimaryRsnie;
1905        BOOLEAN         bMixCipher = FALSE;     // indicate the pairwise and group cipher are different
1906        UCHAR           p_offset;
1907        WPA_MIX_PAIR_CIPHER             FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES;      // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
1908
1909        rsnielen_cur_p = NULL;
1910        rsnielen_ex_cur_p = NULL;
1911
1912        {
1913#ifdef CONFIG_STA_SUPPORT
1914                IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1915                {
1916#ifdef WPA_SUPPLICANT_SUPPORT
1917                        if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
1918                        {
1919                                if (AuthMode < Ndis802_11AuthModeWPA)
1920                                        return;
1921                        }
1922                        else
1923#endif // WPA_SUPPLICANT_SUPPORT //
1924                        {
1925                                // Support WPAPSK or WPA2PSK in STA-Infra mode
1926                                // Support WPANone in STA-Adhoc mode
1927                                if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
1928                                        (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
1929                                        (AuthMode != Ndis802_11AuthModeWPANone)
1930                                        )
1931                                        return;
1932                        }
1933
1934                        DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
1935
1936                        // Zero RSNIE context
1937                        pAd->StaCfg.RSNIE_Len = 0;
1938                        NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1939
1940                        // Pointer to RSNIE
1941                        rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1942                        pRsnIe = pAd->StaCfg.RSN_IE;
1943
1944                        bMixCipher = pAd->StaCfg.bMixCipher;
1945                }
1946#endif // CONFIG_STA_SUPPORT //
1947        }
1948
1949        // indicate primary RSNIE as WPA or WPA2
1950        if ((AuthMode == Ndis802_11AuthModeWPA) ||
1951                (AuthMode == Ndis802_11AuthModeWPAPSK) ||
1952                (AuthMode == Ndis802_11AuthModeWPANone) ||
1953                (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
1954                (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
1955                PrimaryRsnie = WpaIe;
1956        else
1957                PrimaryRsnie = Wpa2Ie;
1958
1959        {
1960                // Build the primary RSNIE
1961                // 1. insert cipher suite
1962                RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
1963
1964                // 2. insert AKM
1965                RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
1966
1967                // 3. insert capability
1968                RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
1969        }
1970
1971        // 4. update the RSNIE length
1972        *rsnielen_cur_p = p_offset;
1973
1974        hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1975
1976
1977}
1978
1979/*
1980    ==========================================================================
1981    Description:
1982                Check whether the received frame is EAP frame.
1983
1984        Arguments:
1985                pAd                             -       pointer to our pAdapter context
1986                pEntry                  -       pointer to active entry
1987                pData                   -       the received frame
1988                DataByteCount   -       the received frame's length
1989                FromWhichBSSID  -       indicate the interface index
1990
1991    Return:
1992         TRUE                   -       This frame is EAP frame
1993         FALSE                  -       otherwise
1994    ==========================================================================
1995*/
1996BOOLEAN RTMPCheckWPAframe(
1997    IN PRTMP_ADAPTER    pAd,
1998    IN PMAC_TABLE_ENTRY pEntry,
1999    IN PUCHAR           pData,
2000    IN ULONG            DataByteCount,
2001        IN UCHAR                        FromWhichBSSID)
2002{
2003        ULONG   Body_len;
2004        BOOLEAN Cancelled;
2005
2006
2007    if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
2008        return FALSE;
2009
2010
2011        // Skip LLC header
2012    if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
2013        // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
2014        NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
2015    {
2016        pData += 6;
2017    }
2018        // Skip 2-bytes EAPoL type
2019    if (NdisEqualMemory(EAPOL, pData, 2))
2020//      if (*(UINT16 *)EAPOL == *(UINT16 *)pData)
2021    {
2022        pData += 2;
2023    }
2024    else
2025        return FALSE;
2026
2027    switch (*(pData+1))
2028    {
2029        case EAPPacket:
2030                        Body_len = (*(pData+2)<<8) | (*(pData+3));
2031            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
2032            break;
2033        case EAPOLStart:
2034            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
2035                        if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2036            {
2037                DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
2038                RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2039                pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2040            }
2041            break;
2042        case EAPOLLogoff:
2043            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
2044            break;
2045        case EAPOLKey:
2046                        Body_len = (*(pData+2)<<8) | (*(pData+3));
2047            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
2048            break;
2049        case EAPOLASFAlert:
2050            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
2051            break;
2052        default:
2053            return FALSE;
2054
2055    }
2056    return TRUE;
2057}
2058
2059/*
2060    ==========================================================================
2061    Description:
2062                Report the EAP message type
2063
2064        Arguments:
2065                msg             -       EAPOL_PAIR_MSG_1
2066                                        EAPOL_PAIR_MSG_2
2067                                        EAPOL_PAIR_MSG_3
2068                                        EAPOL_PAIR_MSG_4
2069                                        EAPOL_GROUP_MSG_1
2070                                        EAPOL_GROUP_MSG_2
2071
2072    Return:
2073         message type string
2074
2075    ==========================================================================
2076*/
2077PSTRING GetEapolMsgType(CHAR msg)
2078{
2079    if(msg == EAPOL_PAIR_MSG_1)
2080        return "Pairwise Message 1";
2081    else if(msg == EAPOL_PAIR_MSG_2)
2082        return "Pairwise Message 2";
2083        else if(msg == EAPOL_PAIR_MSG_3)
2084        return "Pairwise Message 3";
2085        else if(msg == EAPOL_PAIR_MSG_4)
2086        return "Pairwise Message 4";
2087        else if(msg == EAPOL_GROUP_MSG_1)
2088        return "Group Message 1";
2089        else if(msg == EAPOL_GROUP_MSG_2)
2090        return "Group Message 2";
2091    else
2092        return "Invalid Message";
2093}
2094
2095
2096/*
2097    ========================================================================
2098
2099    Routine Description:
2100    Check Sanity RSN IE of EAPoL message
2101
2102    Arguments:
2103
2104    Return Value:
2105
2106
2107    ========================================================================
2108*/
2109BOOLEAN RTMPCheckRSNIE(
2110        IN  PRTMP_ADAPTER   pAd,
2111        IN  PUCHAR          pData,
2112        IN  UCHAR           DataLen,
2113        IN  MAC_TABLE_ENTRY *pEntry,
2114        OUT     UCHAR                   *Offset)
2115{
2116        PUCHAR              pVIE;
2117        UCHAR               len;
2118        PEID_STRUCT         pEid;
2119        BOOLEAN                         result = FALSE;
2120
2121        pVIE = pData;
2122        len      = DataLen;
2123        *Offset = 0;
2124
2125        while (len > sizeof(RSNIE2))
2126        {
2127                pEid = (PEID_STRUCT) pVIE;
2128                // WPA RSN IE
2129                if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
2130                {
2131                        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
2132                                (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
2133                                (pEntry->RSNIE_Len == (pEid->Len + 2)))
2134                        {
2135                                        result = TRUE;
2136                        }
2137
2138                        *Offset += (pEid->Len + 2);
2139                }
2140                // WPA2 RSN IE
2141                else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
2142                {
2143                        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
2144                                (pEid->Eid == pEntry->RSN_IE[0]) &&
2145                                ((pEid->Len + 2) >= pEntry->RSNIE_Len) &&
2146                                (NdisEqualMemory(pEid->Octet, &pEntry->RSN_IE[2], pEntry->RSNIE_Len - 2)))
2147                        {
2148
2149                                        result = TRUE;
2150                        }
2151
2152                        *Offset += (pEid->Len + 2);
2153                }
2154                else
2155                {
2156                        break;
2157                }
2158
2159                pVIE += (pEid->Len + 2);
2160                len  -= (pEid->Len + 2);
2161        }
2162
2163
2164        return result;
2165
2166}
2167
2168
2169/*
2170    ========================================================================
2171
2172    Routine Description:
2173    Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
2174    GTK  is encaptulated in KDE format at  p.83 802.11i D10
2175
2176    Arguments:
2177
2178    Return Value:
2179
2180    Note:
2181        802.11i D10
2182
2183    ========================================================================
2184*/
2185BOOLEAN RTMPParseEapolKeyData(
2186        IN  PRTMP_ADAPTER   pAd,
2187        IN  PUCHAR          pKeyData,
2188        IN  UCHAR           KeyDataLen,
2189        IN      UCHAR                   GroupKeyIndex,
2190        IN      UCHAR                   MsgType,
2191        IN      BOOLEAN                 bWPA2,
2192        IN  MAC_TABLE_ENTRY *pEntry)
2193{
2194    PKDE_ENCAP          pKDE = NULL;
2195    PUCHAR              pMyKeyData = pKeyData;
2196    UCHAR               KeyDataLength = KeyDataLen;
2197    UCHAR               GTKLEN = 0;
2198        UCHAR                           DefaultIdx = 0;
2199        UCHAR                           skip_offset;
2200
2201        // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
2202        if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
2203    {
2204                // Check RSN IE whether it is WPA2/WPA2PSK
2205                if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
2206                {
2207                        // send wireless event - for RSN IE different
2208                        if (pAd->CommonCfg.bWirelessEvent)
2209                                RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
2210
2211                DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
2212                        hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
2213                        hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
2214
2215                        return FALSE;
2216        }
2217        else
2218                {
2219                        if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
2220                        {
2221                                WpaShowAllsuite(pMyKeyData, skip_offset);
2222
2223                                // skip RSN IE
2224                                pMyKeyData += skip_offset;
2225                                KeyDataLength -= skip_offset;
2226                                DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
2227                        }
2228                        else
2229                                return TRUE;
2230                }
2231        }
2232
2233        DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
2234        //hex_dump("remain data", pMyKeyData, KeyDataLength);
2235
2236
2237        // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
2238        if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
2239        {
2240                if (KeyDataLength >= 8) // KDE format exclude GTK length
2241        {
2242                pKDE = (PKDE_ENCAP) pMyKeyData;
2243
2244
2245                        DefaultIdx = pKDE->GTKEncap.Kid;
2246
2247                        // Sanity check - KED length
2248                        if (KeyDataLength < (pKDE->Len + 2))
2249                {
2250                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
2251                        return FALSE;
2252                }
2253
2254                        // Get GTK length - refer to IEEE 802.11i-2004 p.82
2255                        GTKLEN = pKDE->Len -6;
2256                        if (GTKLEN < LEN_AES_KEY)
2257                        {
2258                                DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
2259                        return FALSE;
2260                        }
2261
2262        }
2263                else
2264        {
2265                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
2266                return FALSE;
2267        }
2268
2269                DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
2270                // skip it
2271                pMyKeyData += 8;
2272                KeyDataLength -= 8;
2273
2274        }
2275        else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
2276        {
2277                DefaultIdx = GroupKeyIndex;
2278                DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
2279        }
2280
2281        // Sanity check - shared key index must be 1 ~ 3
2282        if (DefaultIdx < 1 || DefaultIdx > 3)
2283    {
2284        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2285        return FALSE;
2286    }
2287
2288
2289#ifdef CONFIG_STA_SUPPORT
2290        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2291        {
2292                PCIPHER_KEY pSharedKey;
2293
2294                // set key material, TxMic and RxMic
2295                NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2296                pAd->StaCfg.DefaultKeyId = DefaultIdx;
2297
2298                pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
2299
2300                // Prepare pair-wise key information into shared key table
2301                NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
2302                pSharedKey->KeyLen = LEN_TKIP_EK;
2303                NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
2304                NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], LEN_TKIP_RXMICK);
2305                NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], LEN_TKIP_TXMICK);
2306
2307                // Update Shared Key CipherAlg
2308                pSharedKey->CipherAlg = CIPHER_NONE;
2309                if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
2310                        pSharedKey->CipherAlg = CIPHER_TKIP;
2311                else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
2312                        pSharedKey->CipherAlg = CIPHER_AES;
2313                else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
2314                        pSharedKey->CipherAlg = CIPHER_WEP64;
2315                else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
2316                        pSharedKey->CipherAlg = CIPHER_WEP128;
2317
2318
2319                // Update group key information to ASIC Shared Key Table
2320                AsicAddSharedKeyEntry(pAd,
2321                                                          BSS0,
2322                                                          pAd->StaCfg.DefaultKeyId,
2323                                                          pSharedKey->CipherAlg,
2324                                                          pSharedKey->Key,
2325                                                          pSharedKey->TxMic,
2326                                                          pSharedKey->RxMic);
2327
2328                // Update ASIC WCID attribute table and IVEIV table
2329                RTMPAddWcidAttributeEntry(pAd,
2330                                                                  BSS0,
2331                                                                  pAd->StaCfg.DefaultKeyId,
2332                                                                  pSharedKey->CipherAlg,
2333                                                                  NULL);
2334        }
2335#endif // CONFIG_STA_SUPPORT //
2336
2337        return TRUE;
2338
2339}
2340
2341
2342/*
2343        ========================================================================
2344
2345        Routine Description:
2346                Construct EAPoL message for WPA handshaking
2347                Its format is below,
2348
2349                +--------------------+
2350                | Protocol Version       |  1 octet
2351                +--------------------+
2352                | Protocol Type          |      1 octet
2353                +--------------------+
2354                | Body Length            |  2 octets
2355                +--------------------+
2356                | Descriptor Type        |      1 octet
2357                +--------------------+
2358                | Key Information    |  2 octets
2359                +--------------------+
2360                | Key Length         |  1 octet
2361                +--------------------+
2362                | Key Repaly Counter |  8 octets
2363                +--------------------+
2364                | Key Nonce                  |  32 octets
2365                +--------------------+
2366                | Key IV                         |  16 octets
2367                +--------------------+
2368                | Key RSC                        |  8 octets
2369                +--------------------+
2370                | Key ID or Reserved |  8 octets
2371                +--------------------+
2372                | Key MIC                        |      16 octets
2373                +--------------------+
2374                | Key Data Length        |      2 octets
2375                +--------------------+
2376                | Key Data                       |      n octets
2377                +--------------------+
2378
2379
2380        Arguments:
2381                pAd                     Pointer to our adapter
2382
2383        Return Value:
2384                None
2385
2386        Note:
2387
2388        ========================================================================
2389*/
2390VOID    ConstructEapolMsg(
2391        IN      PMAC_TABLE_ENTRY        pEntry,
2392    IN  UCHAR                           GroupKeyWepStatus,
2393    IN  UCHAR                           MsgType,
2394    IN  UCHAR                           DefaultKeyIdx,
2395        IN      UCHAR                           *KeyNonce,
2396        IN      UCHAR                           *TxRSC,
2397        IN      UCHAR                           *GTK,
2398        IN      UCHAR                           *RSNIE,
2399        IN      UCHAR                           RSNIE_Len,
2400    OUT PEAPOL_PACKET       pMsg)
2401{
2402        BOOLEAN bWPA2 = FALSE;
2403        UCHAR   KeyDescVer;
2404
2405        // Choose WPA2 or not
2406        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2407                (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2408                bWPA2 = TRUE;
2409
2410    // Init Packet and Fill header
2411    pMsg->ProVer = EAPOL_VER;
2412    pMsg->ProType = EAPOLKey;
2413
2414        // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
2415        SET_UINT16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
2416
2417        // Fill in EAPoL descriptor
2418        if (bWPA2)
2419                pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2420        else
2421                pMsg->KeyDesc.Type = WPA1_KEY_DESC;
2422
2423        // Key Descriptor Version (bits 0-2) specifies the key descriptor version type
2424        {
2425                // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
2426                // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
2427                KeyDescVer = (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) ||
2428                                        (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
2429        }
2430
2431        pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2432
2433        // Specify Key Type as Group(0) or Pairwise(1)
2434        if (MsgType >= EAPOL_GROUP_MSG_1)
2435                pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
2436        else
2437                pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
2438
2439        // Specify Key Index, only group_msg1_WPA1
2440        if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2441                pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
2442
2443        if (MsgType == EAPOL_PAIR_MSG_3)
2444                pMsg->KeyDesc.KeyInfo.Install = 1;
2445
2446        if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
2447                pMsg->KeyDesc.KeyInfo.KeyAck = 1;
2448
2449        if (MsgType != EAPOL_PAIR_MSG_1)
2450                pMsg->KeyDesc.KeyInfo.KeyMic = 1;
2451
2452        if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
2453                (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
2454    {
2455        pMsg->KeyDesc.KeyInfo.Secure = 1;
2456    }
2457
2458        if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
2459                (MsgType == EAPOL_GROUP_MSG_1)))
2460    {
2461        pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2462    }
2463
2464        // key Information element has done.
2465        *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
2466
2467        // Fill in Key Length
2468        {
2469                if (MsgType >= EAPOL_GROUP_MSG_1)
2470                {
2471                        // the length of group key cipher
2472                        pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
2473                }
2474                else
2475                {
2476                        // the length of pairwise key cipher
2477                        pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
2478                }
2479        }
2480
2481        // Fill in replay counter
2482    NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
2483
2484        // Fill Key Nonce field
2485        // ANonce : pairwise_msg1 & pairwise_msg3
2486        // SNonce : pairwise_msg2
2487        // GNonce : group_msg1_wpa1
2488        if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
2489        NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
2490
2491        // Fill key IV - WPA2 as 0, WPA1 as random
2492        if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
2493        {
2494                // Suggest IV be random number plus some number,
2495                NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
2496        pMsg->KeyDesc.KeyIv[15] += 2;
2497        }
2498
2499    // Fill Key RSC field
2500    // It contains the RSC for the GTK being installed.
2501        if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
2502        {
2503        NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2504        }
2505
2506        // Clear Key MIC field for MIC calculation later
2507    NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
2508
2509        ConstructEapolKeyData(pEntry,
2510                                                  GroupKeyWepStatus,
2511                                                  KeyDescVer,
2512                                                  MsgType,
2513                                                  DefaultKeyIdx,
2514                                                  GTK,
2515                                                  RSNIE,
2516                                                  RSNIE_Len,
2517                                                  pMsg);
2518
2519        // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
2520        if (MsgType != EAPOL_PAIR_MSG_1)
2521        {
2522                CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
2523        }
2524
2525        DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2526        DBGPRINT(RT_DEBUG_TRACE, ("          Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len)));
2527        DBGPRINT(RT_DEBUG_TRACE, ("          Key length  = %d \n", CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyLength)));
2528
2529
2530}
2531
2532/*
2533        ========================================================================
2534
2535        Routine Description:
2536                Construct the Key Data field of EAPoL message
2537
2538        Arguments:
2539                pAd                     Pointer to our adapter
2540                Elem            Message body
2541
2542        Return Value:
2543                None
2544
2545        Note:
2546
2547        ========================================================================
2548*/
2549VOID    ConstructEapolKeyData(
2550        IN      PMAC_TABLE_ENTRY        pEntry,
2551        IN      UCHAR                   GroupKeyWepStatus,
2552        IN      UCHAR                   keyDescVer,
2553        IN      UCHAR                   MsgType,
2554        IN      UCHAR                   DefaultKeyIdx,
2555        IN      UCHAR                   *GTK,
2556        IN      UCHAR                   *RSNIE,
2557        IN      UCHAR                   RSNIE_LEN,
2558        OUT PEAPOL_PACKET   pMsg)
2559{
2560        UCHAR           *mpool, *Key_Data, *Rc4GTK;
2561        UCHAR       ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
2562        ULONG           data_offset;
2563        BOOLEAN         bWPA2Capable = FALSE;
2564        PRTMP_ADAPTER   pAd = pEntry->pAd;
2565        BOOLEAN         GTK_Included = FALSE;
2566
2567        // Choose WPA2 or not
2568        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2569                (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2570                bWPA2Capable = TRUE;
2571
2572        if (MsgType == EAPOL_PAIR_MSG_1 ||
2573                MsgType == EAPOL_PAIR_MSG_4 ||
2574                MsgType == EAPOL_GROUP_MSG_2)
2575                return;
2576
2577        // allocate memory pool
2578        os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500);
2579
2580    if (mpool == NULL)
2581                return;
2582
2583        /* Rc4GTK Len = 512 */
2584        Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
2585        /* Key_Data Len = 512 */
2586        Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
2587
2588        NdisZeroMemory(Key_Data, 512);
2589        SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
2590        data_offset = 0;
2591
2592        // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
2593        if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
2594        {
2595                PUINT8  pmkid_ptr = NULL;
2596                UINT8   pmkid_len = 0;
2597
2598
2599                RTMPInsertRSNIE(&Key_Data[data_offset],
2600                                                (PULONG)&data_offset,
2601                                                RSNIE,
2602                                                RSNIE_LEN,
2603                                                pmkid_ptr,
2604                                                pmkid_len);
2605        }
2606
2607
2608        // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
2609        if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
2610        {
2611                // Key Data Encapsulation (KDE) format - 802.11i-2004  Figure-43w and Table-20h
2612        Key_Data[data_offset + 0] = 0xDD;
2613
2614                if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
2615                {
2616                        Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
2617                }
2618                else
2619                {
2620                        Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
2621                }
2622
2623        Key_Data[data_offset + 2] = 0x00;
2624        Key_Data[data_offset + 3] = 0x0F;
2625        Key_Data[data_offset + 4] = 0xAC;
2626        Key_Data[data_offset + 5] = 0x01;
2627
2628                // GTK KDE format - 802.11i-2004  Figure-43x
2629        Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
2630        Key_Data[data_offset + 7] = 0x00;       // Reserved Byte
2631
2632                data_offset += 8;
2633        }
2634
2635
2636        // Encapsulate GTK
2637        // Only for pairwise_msg3_WPA2 and group_msg1
2638        if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
2639        {
2640                // Fill in GTK
2641                if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
2642                {
2643                        NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
2644                        data_offset += LEN_AES_KEY;
2645                }
2646                else
2647                {
2648                        NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
2649                        data_offset += TKIP_GTK_LENGTH;
2650                }
2651
2652                GTK_Included = TRUE;
2653        }
2654
2655
2656        // This whole key-data field shall be encrypted if a GTK is included.
2657        // Encrypt the data material in key data field with KEK
2658        if (GTK_Included)
2659        {
2660                //hex_dump("GTK_Included", Key_Data, data_offset);
2661
2662                if (
2663                        (keyDescVer == DESC_TYPE_AES))
2664                {
2665                        UCHAR   remainder = 0;
2666                        UCHAR   pad_len = 0;
2667
2668                        // Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394,
2669                        // shall be used to encrypt the Key Data field using the KEK field from
2670                        // the derived PTK.
2671
2672                        // If the Key Data field uses the NIST AES key wrap, then the Key Data field
2673                        // shall be padded before encrypting if the key data length is less than 16
2674                        // octets or if it is not a multiple of 8. The padding consists of appending
2675                        // a single octet 0xdd followed by zero or more 0x00 octets.
2676                        if ((remainder = data_offset & 0x07) != 0)
2677                        {
2678                                INT             i;
2679
2680                                pad_len = (8 - remainder);
2681                                Key_Data[data_offset] = 0xDD;
2682                                for (i = 1; i < pad_len; i++)
2683                                        Key_Data[data_offset + i] = 0;
2684
2685                                data_offset += pad_len;
2686                        }
2687
2688                        AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, data_offset, Rc4GTK);
2689            // AES wrap function will grow 8 bytes in length
2690            data_offset += 8;
2691                }
2692                else
2693                {
2694                        /*      Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
2695                                using the KEK field from the derived PTK. */
2696
2697                        // PREPARE Encrypted  "Key DATA" field.  (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
2698                        // put TxTsc in Key RSC field
2699                        pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32;   //Init crc32.
2700
2701                        // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
2702                        NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
2703                        NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], LEN_EAP_EK);
2704                        ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey));  //INIT SBOX, KEYLEN+3(IV)
2705                        pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
2706                        WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
2707                }
2708
2709                NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
2710        }
2711        else
2712        {
2713                NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
2714        }
2715
2716        // Update key data length field and total body length
2717        SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
2718        INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset);
2719
2720        os_free_mem(NULL, mpool);
2721
2722}
2723
2724/*
2725        ========================================================================
2726
2727        Routine Description:
2728                Calcaulate MIC. It is used during 4-ways handsharking.
2729
2730        Arguments:
2731                pAd                             -       pointer to our pAdapter context
2732        PeerWepStatus   -       indicate the encryption type
2733
2734        Return Value:
2735
2736        Note:
2737
2738        ========================================================================
2739*/
2740static VOID     CalculateMIC(
2741        IN      UCHAR                   KeyDescVer,
2742        IN      UCHAR                   *PTK,
2743        OUT PEAPOL_PACKET   pMsg)
2744{
2745    UCHAR   *OutBuffer;
2746        ULONG   FrameLen = 0;
2747        UCHAR   mic[LEN_KEY_DESC_MIC];
2748        UCHAR   digest[80];
2749
2750        // allocate memory for MIC calculation
2751        os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512);
2752
2753    if (OutBuffer == NULL)
2754    {
2755                DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
2756                return;
2757    }
2758
2759        // make a frame for calculating MIC.
2760    MakeOutgoingFrame(OutBuffer,                &FrameLen,
2761                      CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4,        pMsg,
2762                      END_OF_ARGS);
2763
2764        NdisZeroMemory(mic, sizeof(mic));
2765
2766        // Calculate MIC
2767    if (KeyDescVer == DESC_TYPE_AES)
2768        {
2769                HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer,  FrameLen, digest, SHA1_DIGEST_SIZE);
2770                NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
2771        }
2772        else
2773        {
2774                HMAC_MD5(PTK,  LEN_EAP_MICK, OutBuffer, FrameLen, mic, MD5_DIGEST_SIZE);
2775        }
2776
2777        // store the calculated MIC
2778        NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
2779
2780        os_free_mem(NULL, OutBuffer);
2781}
2782
2783/*
2784        ========================================================================
2785
2786        Routine Description:
2787                Some received frames can't decrypt by Asic, so decrypt them by software.
2788
2789        Arguments:
2790                pAd                             -       pointer to our pAdapter context
2791        PeerWepStatus   -       indicate the encryption type
2792
2793        Return Value:
2794                NDIS_STATUS_SUCCESS             -       decryption successful
2795                NDIS_STATUS_FAILURE             -       decryption failure
2796
2797        ========================================================================
2798*/
2799NDIS_STATUS     RTMPSoftDecryptBroadCastData(
2800        IN      PRTMP_ADAPTER                                   pAd,
2801        IN      RX_BLK                                                  *pRxBlk,
2802        IN  NDIS_802_11_ENCRYPTION_STATUS       GroupCipher,
2803        IN  PCIPHER_KEY                                         pShard_key)
2804{
2805        PRXWI_STRUC                     pRxWI = pRxBlk->pRxWI;
2806
2807
2808
2809        // handle WEP decryption
2810        if (GroupCipher == Ndis802_11Encryption1Enabled)
2811    {
2812                if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
2813                {
2814
2815                        //Minus IV[4] & ICV[4]
2816                        pRxWI->MPDUtotalByteCount -= 8;
2817                }
2818                else
2819                {
2820                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
2821                        // give up this frame
2822                        return NDIS_STATUS_FAILURE;
2823                }
2824        }
2825        // handle TKIP decryption
2826        else if (GroupCipher == Ndis802_11Encryption2Enabled)
2827        {
2828                if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
2829                {
2830
2831                        //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
2832                        pRxWI->MPDUtotalByteCount -= 20;
2833                }
2834        else
2835                {
2836                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
2837                        // give up this frame
2838                        return NDIS_STATUS_FAILURE;
2839        }
2840        }
2841        // handle AES decryption
2842        else if (GroupCipher == Ndis802_11Encryption3Enabled)
2843        {
2844                if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
2845                {
2846
2847                        //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
2848                        pRxWI->MPDUtotalByteCount -= 16;
2849                }
2850                else
2851                {
2852                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
2853                        // give up this frame
2854                        return NDIS_STATUS_FAILURE;
2855                }
2856        }
2857        else
2858        {
2859                // give up this frame
2860                return NDIS_STATUS_FAILURE;
2861        }
2862
2863        return NDIS_STATUS_SUCCESS;
2864
2865}
2866
2867
2868PUINT8  GetSuiteFromRSNIE(
2869                IN      PUINT8  rsnie,
2870                IN      UINT    rsnie_len,
2871                IN      UINT8   type,
2872                OUT     UINT8   *count)
2873{
2874        PEID_STRUCT pEid;
2875        INT                     len;
2876        PUINT8          pBuf;
2877        INT                     offset = 0;
2878        PRSNIE_AUTH     pAkm;
2879        UINT16          acount;
2880        BOOLEAN         isWPA2 = FALSE;
2881
2882        pEid = (PEID_STRUCT)rsnie;
2883        len = rsnie_len - 2;    // exclude IE and length
2884        pBuf = (PUINT8)&pEid->Octet[0];
2885
2886
2887
2888        // set default value
2889        *count = 0;
2890
2891        // Check length
2892        if ((len <= 0) || (pEid->Len != len))
2893        {
2894                DBGPRINT_ERR(("%s : The length is invalid\n", __FUNCTION__));
2895                return NULL;
2896        }
2897
2898        // Check WPA or WPA2
2899        if (pEid->Eid == IE_WPA)
2900        {
2901                PRSNIE  pRsnie = (PRSNIE)pBuf;
2902                UINT16 ucount;
2903
2904                if (len < sizeof(RSNIE))
2905                {
2906                        DBGPRINT_ERR(("%s : The length is too short for WPA\n", __FUNCTION__));
2907                        return NULL;
2908                }
2909
2910                // Get the count of pairwise cipher
2911                ucount = cpu2le16(pRsnie->ucount);
2912                if (ucount > 2)
2913                {
2914                        DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n",
2915                                                                                        __FUNCTION__, ucount));
2916                        return NULL;
2917                }
2918
2919                // Get the group cipher
2920                if (type == GROUP_SUITE)
2921                {
2922                        *count = 1;
2923                        return pRsnie->mcast;
2924                }
2925                // Get the pairwise cipher suite
2926                else if (type == PAIRWISE_SUITE)
2927                {
2928                        DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
2929                                                                                __FUNCTION__, ucount));
2930                        *count = ucount;
2931                        return pRsnie->ucast[0].oui;
2932                }
2933
2934                offset = sizeof(RSNIE) + (4 * (ucount - 1));
2935
2936        }
2937        else if (pEid->Eid == IE_RSN)
2938        {
2939                PRSNIE2 pRsnie = (PRSNIE2)pBuf;
2940                UINT16 ucount;
2941
2942                isWPA2 = TRUE;
2943
2944                if (len < sizeof(RSNIE2))
2945                {
2946                        DBGPRINT_ERR(("%s : The length is too short for WPA2\n", __FUNCTION__));
2947                        return NULL;
2948                }
2949
2950                // Get the count of pairwise cipher
2951                ucount = cpu2le16(pRsnie->ucount);
2952                if (ucount > 2)
2953                {
2954                        DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n",
2955                                                                                        __FUNCTION__, ucount));
2956                        return NULL;
2957                }
2958
2959                // Get the group cipher
2960                if (type == GROUP_SUITE)
2961                {
2962                        *count = 1;
2963                        return pRsnie->mcast;
2964                }
2965                // Get the pairwise cipher suite
2966                else if (type == PAIRWISE_SUITE)
2967                {
2968                        DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
2969                                                                                __FUNCTION__, ucount));
2970                        *count = ucount;
2971                        return pRsnie->ucast[0].oui;
2972                }
2973
2974                offset = sizeof(RSNIE2) + (4 * (ucount - 1));
2975
2976        }
2977        else
2978        {
2979                DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __FUNCTION__, pEid->Eid));
2980                return NULL;
2981        }
2982
2983        // skip group cipher and pairwise cipher suite
2984        pBuf += offset;
2985        len -= offset;
2986
2987        if (len < sizeof(RSNIE_AUTH))
2988        {
2989                DBGPRINT_ERR(("%s : The length of RSNIE is too short\n", __FUNCTION__));
2990                return NULL;
2991        }
2992
2993        // pointer to AKM count
2994        pAkm = (PRSNIE_AUTH)pBuf;
2995
2996        // Get the count of pairwise cipher
2997        acount = cpu2le16(pAkm->acount);
2998        if (acount > 2)
2999        {
3000                DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n",
3001                                                                                __FUNCTION__, acount));
3002                return NULL;
3003        }
3004
3005        // Get the AKM suite
3006        if (type == AKM_SUITE)
3007        {
3008                DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
3009                                                                        __FUNCTION__, acount));
3010                *count = acount;
3011                return pAkm->auth[0].oui;
3012        }
3013        offset = sizeof(RSNIE_AUTH) + (4 * (acount - 1));
3014
3015        pBuf += offset;
3016        len -= offset;
3017
3018        // The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~))
3019        if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID))
3020        {
3021                // Skip RSN capability and PMKID-Count
3022                pBuf += (sizeof(RSN_CAPABILITIES) + 2);
3023                len -= (sizeof(RSN_CAPABILITIES) + 2);
3024
3025                // Get PMKID
3026                if (type == PMKID_LIST)
3027                {
3028                        *count = 1;
3029                        return pBuf;
3030                }
3031        }
3032        else
3033        {
3034                DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __FUNCTION__));
3035                return NULL;
3036        }
3037
3038        *count = 0;
3039        //DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __FUNCTION__, type));
3040        return NULL;
3041
3042}
3043
3044VOID WpaShowAllsuite(
3045        IN      PUINT8  rsnie,
3046        IN      UINT    rsnie_len)
3047{
3048        PUINT8 pSuite = NULL;
3049        UINT8 count;
3050
3051        hex_dump("RSNIE", rsnie, rsnie_len);
3052
3053        // group cipher
3054        if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL)
3055        {
3056                hex_dump("group cipher", pSuite, 4*count);
3057        }
3058
3059        // pairwise cipher
3060        if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL)
3061        {
3062                hex_dump("pairwise cipher", pSuite, 4*count);
3063        }
3064
3065        // AKM
3066        if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL)
3067        {
3068                hex_dump("AKM suite", pSuite, 4*count);
3069        }
3070
3071        // PMKID
3072        if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL)
3073        {
3074                hex_dump("PMKID", pSuite, LEN_PMKID);
3075        }
3076
3077}
3078
3079VOID RTMPInsertRSNIE(
3080        IN PUCHAR pFrameBuf,
3081        OUT PULONG pFrameLen,
3082        IN PUINT8 rsnie_ptr,
3083        IN UINT8  rsnie_len,
3084        IN PUINT8 pmkid_ptr,
3085        IN UINT8  pmkid_len)
3086{
3087        PUCHAR  pTmpBuf;
3088        ULONG   TempLen = 0;
3089        UINT8   extra_len = 0;
3090        UINT16  pmk_count = 0;
3091        UCHAR   ie_num;
3092        UINT8   total_len = 0;
3093    UCHAR       WPA2_OUI[3]={0x00,0x0F,0xAC};
3094
3095        pTmpBuf = pFrameBuf;
3096
3097        /* PMKID-List Must larger than 0 and the multiple of 16. */
3098        if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0))
3099        {
3100                extra_len = sizeof(UINT16) + pmkid_len;
3101
3102                pmk_count = (pmkid_len >> 4);
3103                pmk_count = cpu2le16(pmk_count);
3104        }
3105        else
3106        {
3107                DBGPRINT(RT_DEBUG_WARN, ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
3108                                                                        __FUNCTION__, pmkid_len));
3109        }
3110
3111        if (rsnie_len != 0)
3112        {
3113                ie_num = IE_WPA;
3114                total_len = rsnie_len;
3115
3116                if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI)))
3117                {
3118                        ie_num = IE_RSN;
3119                        total_len += extra_len;
3120                }
3121
3122                /* construct RSNIE body */
3123                MakeOutgoingFrame(pTmpBuf,                      &TempLen,
3124                                                  1,                            &ie_num,
3125                                                  1,                            &total_len,
3126                                                  rsnie_len,            rsnie_ptr,
3127                                                  END_OF_ARGS);
3128
3129                pTmpBuf += TempLen;
3130                *pFrameLen = *pFrameLen + TempLen;
3131
3132                if (ie_num == IE_RSN)
3133                {
3134                        /* Insert PMKID-List field */
3135                        if (extra_len > 0)
3136                        {
3137                                MakeOutgoingFrame(pTmpBuf,                                      &TempLen,
3138                                                                  2,                                            &pmk_count,
3139                                                                  pmkid_len,                            pmkid_ptr,
3140                                                                  END_OF_ARGS);
3141
3142                                pTmpBuf += TempLen;
3143                                *pFrameLen = *pFrameLen + TempLen;
3144                        }
3145                }
3146        }
3147
3148        return;
3149}
3150