linux/drivers/staging/rt2860/sta/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#include "../rt_config.h"
  39
  40#define         WPARSNIE        0xdd
  41#define         WPA2RSNIE       0x30
  42
  43//extern UCHAR BIT8[];
  44UCHAR   CipherWpaPskTkip[] = {
  45                0xDD, 0x16,                             // RSN IE
  46                0x00, 0x50, 0xf2, 0x01, // oui
  47                0x01, 0x00,                             // Version
  48                0x00, 0x50, 0xf2, 0x02, // Multicast
  49                0x01, 0x00,                             // Number of unicast
  50                0x00, 0x50, 0xf2, 0x02, // unicast
  51                0x01, 0x00,                             // number of authentication method
  52                0x00, 0x50, 0xf2, 0x02  // authentication
  53                };
  54UCHAR   CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR));
  55
  56UCHAR   CipherWpaPskAes[] = {
  57                0xDD, 0x16,                     // RSN IE
  58                0x00, 0x50, 0xf2, 0x01, // oui
  59                0x01, 0x00,                             // Version
  60                0x00, 0x50, 0xf2, 0x04, // Multicast
  61                0x01, 0x00,                             // Number of unicast
  62                0x00, 0x50, 0xf2, 0x04, // unicast
  63                0x01, 0x00,                             // number of authentication method
  64                0x00, 0x50, 0xf2, 0x02  // authentication
  65                };
  66UCHAR   CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR));
  67
  68UCHAR   CipherSuiteCiscoCCKM[] = {
  69                0xDD, 0x16,                             // RSN IE
  70                0x00, 0x50, 0xf2, 0x01, // oui
  71                0x01, 0x00,                             // Version
  72                0x00, 0x40, 0x96, 0x01, // Multicast
  73                0x01, 0x00,                             // Number of uicast
  74                0x00, 0x40, 0x96, 0x01, // unicast
  75                0x01, 0x00,                             // number of authentication method
  76                0x00, 0x40, 0x96, 0x00  // Authentication
  77                };
  78UCHAR   CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR));
  79
  80UCHAR   CipherSuiteCiscoCCKM24[] = {
  81                0xDD, 0x18,                             // RSN IE
  82                0x00, 0x50, 0xf2, 0x01, // oui
  83                0x01, 0x00,                             // Version
  84                0x00, 0x40, 0x96, 0x01, // Multicast
  85                0x01, 0x00,                             // Number of uicast
  86                0x00, 0x40, 0x96, 0x01, // unicast
  87                0x01, 0x00,                             // number of authentication method
  88                0x00, 0x40, 0x96, 0x00,
  89                0x28, 0x00// Authentication
  90                };
  91
  92UCHAR   CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR));
  93
  94UCHAR   CipherSuiteCCXTkip[] = {
  95                0xDD, 0x16,                             // RSN IE
  96                0x00, 0x50, 0xf2, 0x01, // oui
  97                0x01, 0x00,                             // Version
  98                0x00, 0x50, 0xf2, 0x02, // Multicast
  99                0x01, 0x00,                             // Number of unicast
 100                0x00, 0x50, 0xf2, 0x02, // unicast
 101                0x01, 0x00,                             // number of authentication method
 102                0x00, 0x50, 0xf2, 0x01  // authentication
 103                };
 104UCHAR   CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR));
 105
 106UCHAR   CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
 107UCHAR   LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
 108
 109UCHAR   EAPOL_FRAME[] = {0x88, 0x8E};
 110
 111BOOLEAN CheckRSNIE(
 112        IN  PRTMP_ADAPTER   pAd,
 113        IN  PUCHAR          pData,
 114        IN  UCHAR           DataLen,
 115        OUT     UCHAR                   *Offset);
 116
 117void inc_byte_array(UCHAR *counter, int len);
 118
 119/*
 120        ========================================================================
 121
 122        Routine Description:
 123                Classify WPA EAP message type
 124
 125        Arguments:
 126                EAPType         Value of EAP message type
 127                MsgType         Internal Message definition for MLME state machine
 128
 129        Return Value:
 130                TRUE            Found appropriate message type
 131                FALSE           No appropriate message type
 132
 133        IRQL = DISPATCH_LEVEL
 134
 135        Note:
 136                All these constants are defined in wpa.h
 137                For supplicant, there is only EAPOL Key message avaliable
 138
 139        ========================================================================
 140*/
 141BOOLEAN WpaMsgTypeSubst(
 142        IN      UCHAR   EAPType,
 143        OUT     INT             *MsgType)
 144{
 145        switch (EAPType)
 146        {
 147                case EAPPacket:
 148                        *MsgType = MT2_EAPPacket;
 149                        break;
 150                case EAPOLStart:
 151                        *MsgType = MT2_EAPOLStart;
 152                        break;
 153                case EAPOLLogoff:
 154                        *MsgType = MT2_EAPOLLogoff;
 155                        break;
 156                case EAPOLKey:
 157                        *MsgType = MT2_EAPOLKey;
 158                        break;
 159                case EAPOLASFAlert:
 160                        *MsgType = MT2_EAPOLASFAlert;
 161                        break;
 162                default:
 163                        return FALSE;
 164        }
 165        return TRUE;
 166}
 167
 168/*
 169        ==========================================================================
 170        Description:
 171                association     state machine init,     including state transition and timer init
 172        Parameters:
 173                S -     pointer to the association state machine
 174        ==========================================================================
 175 */
 176VOID WpaPskStateMachineInit(
 177        IN      PRTMP_ADAPTER   pAd,
 178        IN      STATE_MACHINE *S,
 179        OUT     STATE_MACHINE_FUNC Trans[])
 180{
 181        StateMachineInit(S,     Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE);
 182        StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
 183}
 184
 185/*
 186        ==========================================================================
 187        Description:
 188                This is state machine function.
 189                When receiving EAPOL packets which is  for 802.1x key management.
 190                Use     both in WPA, and WPAPSK case.
 191                In this function, further dispatch to different functions according     to the received packet.  3 categories are :
 192                  1.  normal 4-way pairwisekey and 2-way groupkey handshake
 193                  2.  MIC error (Countermeasures attack)  report packet from STA.
 194                  3.  Request for pairwise/group key update     from STA
 195        Return:
 196        ==========================================================================
 197*/
 198VOID WpaEAPOLKeyAction(
 199        IN      PRTMP_ADAPTER   pAd,
 200        IN      MLME_QUEUE_ELEM *Elem)
 201
 202{
 203        INT             MsgType = EAPOL_MSG_INVALID;
 204        PKEY_DESCRIPTER pKeyDesc;
 205        PHEADER_802_11  pHeader; //red
 206        UCHAR           ZeroReplay[LEN_KEY_DESC_REPLAY];
 207        UCHAR EapolVr;
 208        KEY_INFO                peerKeyInfo;
 209
 210        DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n"));
 211
 212        // Get 802.11 header first
 213        pHeader = (PHEADER_802_11) Elem->Msg;
 214
 215        // Get EAPoL-Key Descriptor
 216        pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)];
 217
 218        NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
 219        NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO));
 220
 221        *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
 222
 223
 224        // 1. Check EAPOL frame version and type
 225        EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H];
 226
 227    if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC)))
 228        {
 229        DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
 230                        return;
 231        }
 232
 233        // First validate replay counter, only accept message with larger replay counter
 234        // Let equal pass, some AP start with all zero replay counter
 235        NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
 236
 237        if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
 238                (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
 239        {
 240                DBGPRINT(RT_DEBUG_ERROR, ("   ReplayCounter not match   \n"));
 241                return;
 242        }
 243
 244        // Process WPA2PSK frame
 245        if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
 246        {
 247                if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
 248                        (peerKeyInfo.EKD_DL == 0) &&
 249                        (peerKeyInfo.KeyAck == 1) &&
 250                        (peerKeyInfo.KeyMic == 0) &&
 251                        (peerKeyInfo.Secure == 0) &&
 252                        (peerKeyInfo.Error == 0) &&
 253                        (peerKeyInfo.Request == 0))
 254                {
 255                        MsgType = EAPOL_PAIR_MSG_1;
 256                        DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n"));
 257                } else if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
 258                        (peerKeyInfo.EKD_DL  == 1) &&
 259                        (peerKeyInfo.KeyAck == 1) &&
 260                        (peerKeyInfo.KeyMic == 1) &&
 261                        (peerKeyInfo.Secure == 1) &&
 262                        (peerKeyInfo.Error == 0) &&
 263                        (peerKeyInfo.Request == 0))
 264                {
 265                        MsgType = EAPOL_PAIR_MSG_3;
 266                        DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n"));
 267                } else if((peerKeyInfo.KeyType == GROUPKEY) &&
 268                        (peerKeyInfo.EKD_DL == 1) &&
 269                        (peerKeyInfo.KeyAck == 1) &&
 270                        (peerKeyInfo.KeyMic == 1) &&
 271                        (peerKeyInfo.Secure == 1) &&
 272                        (peerKeyInfo.Error == 0) &&
 273                        (peerKeyInfo.Request == 0))
 274                {
 275                        MsgType = EAPOL_GROUP_MSG_1;
 276                        DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n"));
 277                }
 278
 279                // We will assume link is up (assoc suceess and port not secured).
 280                // All state has to be able to process message from previous state
 281                switch(pAd->StaCfg.WpaState)
 282                {
 283                case SS_START:
 284                        if(MsgType == EAPOL_PAIR_MSG_1)
 285                        {
 286                                Wpa2PairMsg1Action(pAd, Elem);
 287                                pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
 288                        }
 289                        break;
 290
 291                case SS_WAIT_MSG_3:
 292                        if(MsgType == EAPOL_PAIR_MSG_1)
 293                        {
 294                                Wpa2PairMsg1Action(pAd, Elem);
 295                                pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
 296                        }
 297                        else if(MsgType == EAPOL_PAIR_MSG_3)
 298                        {
 299                                Wpa2PairMsg3Action(pAd, Elem);
 300                                pAd->StaCfg.WpaState = SS_WAIT_GROUP;
 301                        }
 302                        break;
 303
 304                case SS_WAIT_GROUP:             // When doing group key exchange
 305                case SS_FINISH:                 // This happened when update group key
 306                        if(MsgType == EAPOL_PAIR_MSG_1)
 307                        {
 308                            // Reset port secured variable
 309                                pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
 310                                Wpa2PairMsg1Action(pAd, Elem);
 311                                pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
 312                        }
 313                        else if(MsgType == EAPOL_PAIR_MSG_3)
 314                        {
 315                            // Reset port secured variable
 316                                pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
 317                                Wpa2PairMsg3Action(pAd, Elem);
 318                                pAd->StaCfg.WpaState = SS_WAIT_GROUP;
 319                        }
 320                        else if(MsgType == EAPOL_GROUP_MSG_1)
 321                        {
 322                                WpaGroupMsg1Action(pAd, Elem);
 323                                pAd->StaCfg.WpaState = SS_FINISH;
 324                        }
 325                        break;
 326
 327                default:
 328                        break;
 329                }
 330        }
 331        // Process WPAPSK Frame
 332        // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant
 333        else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
 334        {
 335                if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
 336                        (peerKeyInfo.KeyIndex == 0) &&
 337                        (peerKeyInfo.KeyAck == 1) &&
 338                        (peerKeyInfo.KeyMic == 0) &&
 339                        (peerKeyInfo.Secure == 0) &&
 340                        (peerKeyInfo.Error == 0) &&
 341                        (peerKeyInfo.Request == 0))
 342                {
 343                        MsgType = EAPOL_PAIR_MSG_1;
 344                        DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n"));
 345                }
 346                else if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
 347                        (peerKeyInfo.KeyIndex == 0) &&
 348                        (peerKeyInfo.KeyAck == 1) &&
 349                        (peerKeyInfo.KeyMic == 1) &&
 350                        (peerKeyInfo.Secure == 0) &&
 351                        (peerKeyInfo.Error == 0) &&
 352                        (peerKeyInfo.Request == 0))
 353                {
 354                        MsgType = EAPOL_PAIR_MSG_3;
 355                        DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n"));
 356                }
 357                else if((peerKeyInfo.KeyType == GROUPKEY) &&
 358                        (peerKeyInfo.KeyIndex != 0) &&
 359                        (peerKeyInfo.KeyAck == 1) &&
 360                        (peerKeyInfo.KeyMic == 1) &&
 361                        (peerKeyInfo.Secure == 1) &&
 362                        (peerKeyInfo.Error == 0) &&
 363                        (peerKeyInfo.Request == 0))
 364                {
 365                        MsgType = EAPOL_GROUP_MSG_1;
 366                        DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n"));
 367                }
 368
 369                // We will assume link is up (assoc suceess and port not secured).
 370                // All state has to be able to process message from previous state
 371                switch(pAd->StaCfg.WpaState)
 372                {
 373                case SS_START:
 374                        if(MsgType == EAPOL_PAIR_MSG_1)
 375                        {
 376                                WpaPairMsg1Action(pAd, Elem);
 377                                pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
 378                        }
 379                        break;
 380
 381                case SS_WAIT_MSG_3:
 382                        if(MsgType == EAPOL_PAIR_MSG_1)
 383                        {
 384                                WpaPairMsg1Action(pAd, Elem);
 385                                pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
 386                        }
 387                        else if(MsgType == EAPOL_PAIR_MSG_3)
 388                        {
 389                                WpaPairMsg3Action(pAd, Elem);
 390                                pAd->StaCfg.WpaState = SS_WAIT_GROUP;
 391                        }
 392                        break;
 393
 394                case SS_WAIT_GROUP:             // When doing group key exchange
 395                case SS_FINISH:                 // This happened when update group key
 396                        if(MsgType == EAPOL_PAIR_MSG_1)
 397                        {
 398                                WpaPairMsg1Action(pAd, Elem);
 399                                pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
 400                                // Reset port secured variable
 401                                pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
 402                        }
 403                        else if(MsgType == EAPOL_PAIR_MSG_3)
 404                        {
 405                                WpaPairMsg3Action(pAd, Elem);
 406                                pAd->StaCfg.WpaState = SS_WAIT_GROUP;
 407                                // Reset port secured variable
 408                                pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
 409                        }
 410                        else if(MsgType == EAPOL_GROUP_MSG_1)
 411                        {
 412                                WpaGroupMsg1Action(pAd, Elem);
 413                                pAd->StaCfg.WpaState = SS_FINISH;
 414                        }
 415                        break;
 416
 417                default:
 418                        break;
 419                }
 420        }
 421
 422        DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaEAPOLKeyAction\n"));
 423}
 424
 425/*
 426        ========================================================================
 427
 428        Routine Description:
 429                Process Pairwise key 4-way handshaking
 430
 431        Arguments:
 432                pAd     Pointer to our adapter
 433                Elem            Message body
 434
 435        Return Value:
 436                None
 437
 438        Note:
 439
 440        ========================================================================
 441*/
 442VOID    WpaPairMsg1Action(
 443        IN  PRTMP_ADAPTER   pAd,
 444        IN  MLME_QUEUE_ELEM *Elem)
 445{
 446        PHEADER_802_11      pHeader;
 447        UCHAR                           *mpool, *PTK, *digest;
 448        PUCHAR              pOutBuffer = NULL;
 449        UCHAR               Header802_3[14];
 450        ULONG               FrameLen = 0;
 451        PEAPOL_PACKET       pMsg1;
 452        EAPOL_PACKET        Packet;
 453        UCHAR               Mic[16];
 454
 455        DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action ----->\n"));
 456
 457        // allocate memory pool
 458        os_alloc_mem(pAd, (PUCHAR *)&mpool, 256);
 459
 460        if (mpool == NULL)
 461                return;
 462
 463        // PTK Len = 80.
 464        PTK = (UCHAR *) ROUND_UP(mpool, 4);
 465        // digest Len = 80.
 466        digest = (UCHAR *) ROUND_UP(PTK + 80, 4);
 467
 468        pHeader = (PHEADER_802_11) Elem->Msg;
 469
 470        // Process message 1 from authenticator
 471        pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 472
 473        // 1. Save Replay counter, it will use to verify message 3 and construct message 2
 474        NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
 475
 476        // 2. Save ANonce
 477        NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
 478
 479        // Generate random SNonce
 480        GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce);
 481
 482        // Calc PTK(ANonce, SNonce)
 483        WpaCountPTK(pAd,
 484                pAd->StaCfg.PMK,
 485                pAd->StaCfg.ANonce,
 486                pAd->CommonCfg.Bssid,
 487                pAd->StaCfg.SNonce,
 488                pAd->CurrentAddress,
 489                PTK,
 490                LEN_PTK);
 491
 492        // Save key to PTK entry
 493        NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK);
 494
 495        // init 802.3 header and Fill Packet
 496        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
 497
 498        // Zero Message 2 body
 499        NdisZeroMemory(&Packet, sizeof(Packet));
 500        Packet.ProVer   = EAPOL_VER;
 501        Packet.ProType  = EAPOLKey;
 502        //
 503        // Message 2 as  EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
 504        //
 505        Packet.KeyDesc.Type = WPA1_KEY_DESC;
 506        // 1. Key descriptor version and appropriate RSN IE
 507        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
 508        {
 509                Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
 510        }
 511        else      // TKIP
 512        {
 513                Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
 514        }
 515
 516        // fill in Data Material and its length
 517        Packet.KeyDesc.KeyData[0] = IE_WPA;
 518        Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len;
 519        Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2;
 520        NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
 521
 522        // Update packet length after decide Key data payload
 523        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
 524
 525        // Update Key length
 526        Packet.KeyDesc.KeyLength[0] = pMsg1->KeyDesc.KeyLength[0];
 527        Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1];
 528        // 2. Key Type PeerKey
 529        Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
 530
 531        // 3. KeyMic field presented
 532        Packet.KeyDesc.KeyInfo.KeyMic  = 1;
 533
 534        //Convert to little-endian format.
 535        *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
 536
 537
 538        // 4. Fill SNonce
 539        NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE);
 540
 541        // 5. Key Replay Count
 542        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
 543
 544        // Send EAPOL(0, 1, 0, 0, 0, P, 0, SNonce, MIC, RSN_IE)
 545        // Out buffer for transmitting message 2
 546        MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
 547        if(pOutBuffer == NULL)
 548        {
 549                os_free_mem(pAd, mpool);
 550                return;
 551        }
 552        // Prepare EAPOL frame for MIC calculation
 553        // Be careful, only EAPOL frame is counted for MIC calculation
 554        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
 555                Packet.Body_Len[1] + 4,    &Packet,
 556                END_OF_ARGS);
 557
 558        // 6. Prepare and Fill MIC value
 559        NdisZeroMemory(Mic, sizeof(Mic));
 560        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
 561        {       // AES
 562
 563                HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
 564                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
 565        }
 566        else
 567        {       // TKIP
 568                hmac_md5(PTK,  LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
 569        }
 570        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
 571
 572        //hex_dump("MIC", Mic, LEN_KEY_DESC_MIC);
 573
 574                MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
 575                                                LENGTH_802_3,                           &Header802_3,
 576                                                Packet.Body_Len[1] + 4,    &Packet,
 577                                                END_OF_ARGS);
 578
 579
 580        // 5. Copy frame to Tx ring and send Msg 2 to authenticator
 581        RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
 582
 583        MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
 584        os_free_mem(pAd, (PUCHAR)mpool);
 585
 586        DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action <-----\n"));
 587}
 588
 589VOID Wpa2PairMsg1Action(
 590        IN  PRTMP_ADAPTER   pAd,
 591        IN  MLME_QUEUE_ELEM *Elem)
 592{
 593        PHEADER_802_11      pHeader;
 594        UCHAR                           *mpool, *PTK, *digest;
 595        PUCHAR              pOutBuffer = NULL;
 596        UCHAR               Header802_3[14];
 597        ULONG               FrameLen = 0;
 598        PEAPOL_PACKET       pMsg1;
 599        EAPOL_PACKET        Packet;
 600        UCHAR               Mic[16];
 601
 602        DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action ----->\n"));
 603
 604        // allocate memory pool
 605        os_alloc_mem(pAd, (PUCHAR *)&mpool, 256);
 606
 607        if (mpool == NULL)
 608                return;
 609
 610        // PTK Len = 80.
 611        PTK = (UCHAR *) ROUND_UP(mpool, 4);
 612        // digest Len = 80.
 613        digest = (UCHAR *) ROUND_UP(PTK + 80, 4);
 614
 615        pHeader = (PHEADER_802_11) Elem->Msg;
 616
 617        // Process message 1 from authenticator
 618                pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 619
 620        // 1. Save Replay counter, it will use to verify message 3 and construct message 2
 621        NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
 622
 623        // 2. Save ANonce
 624        NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
 625
 626        // Generate random SNonce
 627        GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce);
 628
 629        if(pMsg1->KeyDesc.KeyDataLen[1] > 0 )
 630        {
 631                // cached PMKID
 632        }
 633
 634        // Calc PTK(ANonce, SNonce)
 635        WpaCountPTK(pAd,
 636                pAd->StaCfg.PMK,
 637                pAd->StaCfg.ANonce,
 638                pAd->CommonCfg.Bssid,
 639                pAd->StaCfg.SNonce,
 640                pAd->CurrentAddress,
 641                PTK,
 642                LEN_PTK);
 643
 644        // Save key to PTK entry
 645        NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK);
 646
 647        // init 802.3 header and Fill Packet
 648        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
 649
 650        // Zero message 2 body
 651        NdisZeroMemory(&Packet, sizeof(Packet));
 652        Packet.ProVer   = EAPOL_VER;
 653        Packet.ProType  = EAPOLKey;
 654        //
 655        // Message 2 as  EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
 656        //
 657        Packet.KeyDesc.Type = WPA2_KEY_DESC;
 658
 659        // 1. Key descriptor version and appropriate RSN IE
 660        if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
 661        {
 662                Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
 663        }
 664        else      // TKIP
 665        {
 666                Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
 667        }
 668
 669        // fill in Data Material and its length
 670        Packet.KeyDesc.KeyData[0] = IE_WPA2;
 671        Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len;
 672        Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2;
 673        NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
 674
 675        // Update packet length after decide Key data payload
 676        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
 677
 678        // 2. Key Type PeerKey
 679        Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
 680
 681        // 3. KeyMic field presented
 682        Packet.KeyDesc.KeyInfo.KeyMic  = 1;
 683
 684        // Update Key Length
 685        Packet.KeyDesc.KeyLength[0] = 0;
 686        Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1];
 687
 688        // 4. Fill SNonce
 689        NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE);
 690
 691        // 5. Key Replay Count
 692        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
 693
 694        // Convert to little-endian format.
 695        *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
 696
 697        // Send EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
 698        // Out buffer for transmitting message 2
 699        MlmeAllocateMemory(pAd,  (PUCHAR *)&pOutBuffer);  // allocate memory
 700        if(pOutBuffer == NULL)
 701        {
 702                os_free_mem(pAd, mpool);
 703                return;
 704        }
 705
 706        // Prepare EAPOL frame for MIC calculation
 707        // Be careful, only EAPOL frame is counted for MIC calculation
 708        MakeOutgoingFrame(pOutBuffer,        &FrameLen,
 709                Packet.Body_Len[1] + 4, &Packet,
 710                END_OF_ARGS);
 711
 712        // 6. Prepare and Fill MIC value
 713        NdisZeroMemory(Mic, sizeof(Mic));
 714        if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
 715        {
 716                // AES
 717                HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
 718                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
 719        }
 720        else
 721        {
 722                hmac_md5(PTK,  LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
 723        }
 724        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
 725
 726
 727        // Make  Transmitting frame
 728        MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
 729                                                LENGTH_802_3,                   &Header802_3,
 730                                                Packet.Body_Len[1] + 4, &Packet,
 731                                                END_OF_ARGS);
 732
 733
 734        // 5. Copy frame to Tx ring
 735        RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
 736
 737        MlmeFreeMemory(pAd, pOutBuffer);
 738        os_free_mem(pAd, mpool);
 739
 740        DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action <-----\n"));
 741
 742}
 743
 744/*
 745        ========================================================================
 746
 747        Routine Description:
 748                Process Pairwise key 4-way handshaking
 749
 750        Arguments:
 751                pAd     Pointer to our adapter
 752                Elem            Message body
 753
 754        Return Value:
 755                None
 756
 757        Note:
 758
 759        ========================================================================
 760*/
 761VOID    WpaPairMsg3Action(
 762        IN      PRTMP_ADAPTER   pAd,
 763        IN      MLME_QUEUE_ELEM *Elem)
 764
 765{
 766        PHEADER_802_11      pHeader;
 767        PUCHAR                  pOutBuffer = NULL;
 768        UCHAR               Header802_3[14];
 769        ULONG                   FrameLen = 0;
 770        EAPOL_PACKET        Packet;
 771        PEAPOL_PACKET       pMsg3;
 772        UCHAR                   Mic[16], OldMic[16];
 773        MAC_TABLE_ENTRY         *pEntry = NULL;
 774        UCHAR                           skip_offset;
 775        KEY_INFO                        peerKeyInfo;
 776
 777        DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action ----->\n"));
 778
 779        // Record 802.11 header & the received EAPOL packet Msg3
 780        pHeader = (PHEADER_802_11) Elem->Msg;
 781        pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
 782
 783        NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
 784        NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO));
 785
 786        *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
 787
 788
 789        // 1. Verify cipher type match
 790        if (pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2))
 791        {
 792                return;
 793        }
 794        else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
 795        {
 796                return;
 797        }
 798
 799        // Verify RSN IE
 800        //if (!RTMPEqualMemory(pMsg3->KeyDesc.KeyData, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len))
 801        if (!CheckRSNIE(pAd, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1], &skip_offset))
 802        {
 803                DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in Msg 3 of WPA1 4-way handshake!! \n"));
 804                hex_dump("The original RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
 805                hex_dump("The received RSN_IE", pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]);
 806                return;
 807        }
 808        else
 809                DBGPRINT(RT_DEBUG_TRACE, ("RSN_IE VALID in Msg 3 of WPA1 4-way handshake!! \n"));
 810
 811
 812        // 2. Check MIC value
 813        // Save the MIC and replace with zero
 814        NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
 815        NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
 816        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
 817        {
 818                // AES
 819                UCHAR digest[80];
 820
 821                HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
 822                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
 823        }
 824        else    // TKIP
 825        {
 826                hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic);
 827        }
 828
 829        if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
 830        {
 831                DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n"));
 832                return;
 833        }
 834        else
 835                DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n"));
 836
 837        // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
 838        if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
 839                return;
 840
 841        // Update new replay counter
 842        NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
 843
 844        // 4. Double check ANonce
 845        if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
 846                return;
 847
 848        // init 802.3 header and Fill Packet
 849        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
 850
 851        // Zero Message 4 body
 852        NdisZeroMemory(&Packet, sizeof(Packet));
 853        Packet.ProVer   = EAPOL_VER;
 854        Packet.ProType  = EAPOLKey;
 855        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;                // No data field
 856
 857        //
 858        // Message 4 as  EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
 859        //
 860        Packet.KeyDesc.Type = WPA1_KEY_DESC;
 861
 862        // Key descriptor version and appropriate RSN IE
 863        Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
 864
 865        // Update Key Length
 866        Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0];
 867        Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1];
 868
 869        // Key Type PeerKey
 870        Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
 871
 872        // KeyMic field presented
 873        Packet.KeyDesc.KeyInfo.KeyMic  = 1;
 874
 875        // In Msg3,  KeyInfo.secure =0 if Group Key HS to come. 1 if no group key HS
 876        // Station sends Msg4  KeyInfo.secure should be the same as that in Msg.3
 877        Packet.KeyDesc.KeyInfo.Secure= peerKeyInfo.Secure;
 878
 879        // Convert to little-endian format.
 880        *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
 881
 882        // Key Replay count
 883        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
 884
 885        // Out buffer for transmitting message 4
 886        MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
 887        if(pOutBuffer == NULL)
 888                return;
 889
 890        // Prepare EAPOL frame for MIC calculation
 891        // Be careful, only EAPOL frame is counted for MIC calculation
 892        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
 893                Packet.Body_Len[1] + 4,    &Packet,
 894                END_OF_ARGS);
 895
 896        // Prepare and Fill MIC value
 897        NdisZeroMemory(Mic, sizeof(Mic));
 898        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
 899        {
 900                // AES
 901                UCHAR digest[80];
 902
 903                HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
 904                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
 905        }
 906        else
 907        {
 908                hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
 909        }
 910        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
 911
 912        // Update PTK
 913        // Prepare pair-wise key information into shared key table
 914        NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
 915        pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
 916    NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
 917        NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
 918        NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
 919
 920        // Decide its ChiperAlg
 921        if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
 922                pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
 923        else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
 924                pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
 925        else
 926                pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
 927
 928        // Update these related information to MAC_TABLE_ENTRY
 929        pEntry = &pAd->MacTab.Content[BSSID_WCID];
 930        NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
 931        NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
 932        NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
 933        pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
 934
 935        // Update pairwise key information to ASIC Shared Key Table
 936        AsicAddSharedKeyEntry(pAd,
 937                                                  BSS0,
 938                                                  0,
 939                                                  pAd->SharedKey[BSS0][0].CipherAlg,
 940                                                  pAd->SharedKey[BSS0][0].Key,
 941                                                  pAd->SharedKey[BSS0][0].TxMic,
 942                                                  pAd->SharedKey[BSS0][0].RxMic);
 943
 944        // Update ASIC WCID attribute table and IVEIV table
 945        RTMPAddWcidAttributeEntry(pAd,
 946                                                          BSS0,
 947                                                          0,
 948                                                          pAd->SharedKey[BSS0][0].CipherAlg,
 949                                                          pEntry);
 950
 951        // Make transmitting frame
 952        MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
 953                                                LENGTH_802_3,                   &Header802_3,
 954                                                Packet.Body_Len[1] + 4, &Packet,
 955                                                END_OF_ARGS);
 956
 957
 958        // Copy frame to Tx ring and Send Message 4 to authenticator
 959        RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
 960
 961        MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
 962
 963        DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action <-----\n"));
 964}
 965
 966VOID    Wpa2PairMsg3Action(
 967        IN  PRTMP_ADAPTER   pAd,
 968        IN  MLME_QUEUE_ELEM *Elem)
 969
 970{
 971        PHEADER_802_11      pHeader;
 972        PUCHAR              pOutBuffer = NULL;
 973        UCHAR               Header802_3[14];
 974        ULONG               FrameLen = 0;
 975        EAPOL_PACKET        Packet;
 976        PEAPOL_PACKET       pMsg3;
 977        UCHAR               Mic[16], OldMic[16];
 978        UCHAR               *mpool, *KEYDATA, *digest;
 979        UCHAR               Key[32];
 980        MAC_TABLE_ENTRY         *pEntry = NULL;
 981        KEY_INFO                        peerKeyInfo;
 982
 983        // allocate memory
 984        os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024);
 985
 986        if(mpool == NULL)
 987                return;
 988
 989        // KEYDATA Len = 512.
 990        KEYDATA = (UCHAR *) ROUND_UP(mpool, 4);
 991        // digest Len = 80.
 992        digest = (UCHAR *) ROUND_UP(KEYDATA + 512, 4);
 993
 994        DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg3Action ----->\n"));
 995
 996        pHeader = (PHEADER_802_11) Elem->Msg;
 997
 998        // Process message 3 frame.
 999        pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1000
1001        NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
1002        NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO));
1003
1004        *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
1005
1006        // 1. Verify cipher type match
1007        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer!= 2))
1008        {
1009                os_free_mem(pAd, (PUCHAR)mpool);
1010                return;
1011        }
1012        else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
1013        {
1014                os_free_mem(pAd, (PUCHAR)mpool);
1015                return;
1016        }
1017
1018        // 2. Check MIC value
1019        // Save the MIC and replace with zero
1020        NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1021        NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1022        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1023        {
1024                // AES
1025                HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1026                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1027        }
1028        else
1029        {
1030                hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic);
1031        }
1032
1033        if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
1034        {
1035                DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n"));
1036                os_free_mem(pAd, (PUCHAR)mpool);
1037                return;
1038        }
1039        else
1040                DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n"));
1041
1042        // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
1043        if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
1044        {
1045                os_free_mem(pAd, (PUCHAR)mpool);
1046                return;
1047        }
1048
1049        // Update new replay counter
1050        NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1051
1052        // 4. Double check ANonce
1053        if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
1054        {
1055                os_free_mem(pAd, (PUCHAR)mpool);
1056                return;
1057        }
1058
1059        // Obtain GTK
1060        // 5. Decrypt GTK from Key Data
1061        DBGPRINT_RAW(RT_DEBUG_TRACE, ("EKD = %d\n", peerKeyInfo.EKD_DL));
1062        if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1063        {
1064                // Decrypt AES GTK
1065                AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pMsg3->KeyDesc.KeyDataLen[1],pMsg3->KeyDesc.KeyData);
1066        }
1067        else      // TKIP
1068        {
1069                INT i;
1070                // Decrypt TKIP GTK
1071                // Construct 32 bytes RC4 Key
1072                NdisMoveMemory(Key, pMsg3->KeyDesc.KeyIv, 16);
1073                NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16);
1074                ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
1075                //discard first 256 bytes
1076                for(i = 0; i < 256; i++)
1077                        ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
1078                // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
1079                ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]);
1080        }
1081
1082        if (!ParseKeyData(pAd, KEYDATA, pMsg3->KeyDesc.KeyDataLen[1], 1))
1083        {
1084                os_free_mem(pAd, (PUCHAR)mpool);
1085                return;
1086        }
1087
1088        // Update GTK to ASIC
1089        // Update group key information to ASIC Shared Key Table
1090        AsicAddSharedKeyEntry(pAd,
1091                                                  BSS0,
1092                                                  pAd->StaCfg.DefaultKeyId,
1093                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1094                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
1095                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
1096                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
1097
1098        // Update ASIC WCID attribute table and IVEIV table
1099        RTMPAddWcidAttributeEntry(pAd,
1100                                                          BSS0,
1101                                                          pAd->StaCfg.DefaultKeyId,
1102                                                          pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1103                                                          NULL);
1104
1105        // init 802.3 header and Fill Packet
1106        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1107
1108        // Zero message 4 body
1109        NdisZeroMemory(&Packet, sizeof(Packet));
1110        Packet.ProVer   = EAPOL_VER;
1111        Packet.ProType  = EAPOLKey;
1112        Packet.Body_Len[1]      = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;            // No data field
1113
1114        //
1115        // Message 4 as  EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
1116        //
1117        Packet.KeyDesc.Type = WPA2_KEY_DESC;
1118
1119        // Key descriptor version and appropriate RSN IE
1120        Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
1121
1122        // Update Key Length
1123        Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0];
1124        Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1];
1125
1126        // Key Type PeerKey
1127        Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1128
1129        // KeyMic field presented
1130        Packet.KeyDesc.KeyInfo.KeyMic  = 1;
1131        Packet.KeyDesc.KeyInfo.Secure = 1;
1132
1133        // Convert to little-endian format.
1134        *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
1135
1136        // Key Replay count
1137        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1138
1139        // Out buffer for transmitting message 4
1140        MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
1141        if(pOutBuffer == NULL)
1142        {
1143                os_free_mem(pAd, (PUCHAR)mpool);
1144                return;
1145        }
1146
1147        // Prepare EAPOL frame for MIC calculation
1148        // Be careful, only EAPOL frame is counted for MIC calculation
1149        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1150                Packet.Body_Len[1] + 4,    &Packet,
1151                END_OF_ARGS);
1152
1153        // Prepare and Fill MIC value
1154        NdisZeroMemory(Mic, sizeof(Mic));
1155        if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1156        {
1157                // AES
1158                HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1159                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1160        }
1161        else
1162        {
1163                hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
1164        }
1165        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
1166
1167        // Update PTK
1168        // Prepare pair-wise key information into shared key table
1169        NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
1170        pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
1171    NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
1172        NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
1173        NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
1174
1175        // Decide its ChiperAlg
1176        if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
1177                pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
1178        else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
1179                pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
1180        else
1181                pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
1182
1183        // Update these related information to MAC_TABLE_ENTRY
1184        pEntry = &pAd->MacTab.Content[BSSID_WCID];
1185        NdisMoveMemory(&pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
1186        NdisMoveMemory(&pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
1187        NdisMoveMemory(&pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
1188        pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1189
1190        // Update pairwise key information to ASIC Shared Key Table
1191        AsicAddSharedKeyEntry(pAd,
1192                                                  BSS0,
1193                                                  0,
1194                                                  pAd->SharedKey[BSS0][0].CipherAlg,
1195                                                  pAd->SharedKey[BSS0][0].Key,
1196                                                  pAd->SharedKey[BSS0][0].TxMic,
1197                                                  pAd->SharedKey[BSS0][0].RxMic);
1198
1199        // Update ASIC WCID attribute table and IVEIV table
1200        RTMPAddWcidAttributeEntry(pAd,
1201                                                          BSS0,
1202                                                          0,
1203                                                          pAd->SharedKey[BSS0][0].CipherAlg,
1204                                                          pEntry);
1205
1206        // Make  Transmitting frame
1207        MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
1208                                                LENGTH_802_3,                   &Header802_3,
1209                                                Packet.Body_Len[1] + 4, &Packet,
1210                                                END_OF_ARGS);
1211
1212
1213        // Copy frame to Tx ring and Send Message 4 to authenticator
1214        RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
1215
1216        // set 802.1x port control
1217        STA_PORT_SECURED(pAd);
1218
1219    // Indicate Connected for GUI
1220    pAd->IndicateMediaState = NdisMediaStateConnected;
1221
1222        MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
1223        os_free_mem(pAd, (PUCHAR)mpool);
1224
1225
1226        // send wireless event - for set key done WPA2
1227        if (pAd->CommonCfg.bWirelessEvent)
1228                RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, BSS0, 0);
1229
1230        DBGPRINT(RT_DEBUG_ERROR, ("Wpa2PairMsg3Action <-----\n"));
1231
1232}
1233
1234/*
1235        ========================================================================
1236
1237        Routine Description:
1238                Process Group key 2-way handshaking
1239
1240        Arguments:
1241                pAd     Pointer to our adapter
1242                Elem            Message body
1243
1244        Return Value:
1245                None
1246
1247        Note:
1248
1249        ========================================================================
1250*/
1251VOID    WpaGroupMsg1Action(
1252        IN      PRTMP_ADAPTER   pAd,
1253        IN      MLME_QUEUE_ELEM *Elem)
1254
1255{
1256        PUCHAR              pOutBuffer = NULL;
1257        UCHAR               Header802_3[14];
1258        ULONG               FrameLen = 0;
1259        EAPOL_PACKET        Packet;
1260        PEAPOL_PACKET       pGroup;
1261        UCHAR               *mpool, *digest, *KEYDATA;
1262        UCHAR               Mic[16], OldMic[16];
1263        UCHAR               GTK[32], Key[32];
1264        KEY_INFO                        peerKeyInfo;
1265
1266        // allocate memory
1267        os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024);
1268
1269        if(mpool == NULL)
1270                return;
1271
1272        // digest Len = 80.
1273        digest = (UCHAR *) ROUND_UP(mpool, 4);
1274        // KEYDATA Len = 512.
1275        KEYDATA = (UCHAR *) ROUND_UP(digest + 80, 4);
1276
1277        DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action ----->\n"));
1278
1279        // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)
1280        pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1281
1282        NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
1283        NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pGroup->KeyDesc.KeyInfo, sizeof(KEY_INFO));
1284
1285        *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
1286
1287        // 0. Check cipher type match
1288        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2))
1289        {
1290                os_free_mem(pAd, (PUCHAR)mpool);
1291                return;
1292        }
1293        else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
1294        {
1295                os_free_mem(pAd, (PUCHAR)mpool);
1296                return;
1297        }
1298
1299        // 1. Verify Replay counter
1300        //    Check Replay Counter, it has to be larger than last one. No need to be exact one larger
1301        if(RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
1302        {
1303                os_free_mem(pAd, (PUCHAR)mpool);
1304                return;
1305        }
1306
1307        // Update new replay counter
1308        NdisMoveMemory(pAd->StaCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1309
1310        // 2. Verify MIC is valid
1311        // Save the MIC and replace with zero
1312        NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1313        NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1314
1315        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
1316        {       // AES
1317                HMAC_SHA1((PUCHAR) pGroup, pGroup->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1318                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1319        }
1320        else
1321        {       // TKIP
1322                hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Body_Len[1] + 4, Mic);
1323        }
1324
1325        if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
1326        {
1327                DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n"));
1328                MlmeFreeMemory(pAd, (PUCHAR)mpool);
1329                return;
1330        }
1331        else
1332                DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n"));
1333
1334
1335        // 3. Decrypt GTK from Key Data
1336        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1337        {
1338                // Decrypt AES GTK
1339                AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA,  pGroup->KeyDesc.KeyDataLen[1], pGroup->KeyDesc.KeyData);
1340        }
1341        else    // TKIP
1342        {
1343                INT i;
1344
1345                // Decrypt TKIP GTK
1346                // Construct 32 bytes RC4 Key
1347                NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16);
1348                NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16);
1349                ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
1350                //discard first 256 bytes
1351                for(i = 0; i < 256; i++)
1352                        ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
1353                // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
1354                ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pGroup->KeyDesc.KeyData, pGroup->KeyDesc.KeyDataLen[1]);
1355        }
1356
1357        // Process decrypted key data material
1358        // Parse keyData to handle KDE format for WPA2PSK
1359        if (peerKeyInfo.EKD_DL)
1360        {
1361                if (!ParseKeyData(pAd, KEYDATA, pGroup->KeyDesc.KeyDataLen[1], 0))
1362                {
1363                        os_free_mem(pAd, (PUCHAR)mpool);
1364                        return;
1365                }
1366        }
1367        else    // WPAPSK
1368        {
1369                // set key material, TxMic and RxMic for WPAPSK
1370                NdisMoveMemory(GTK, KEYDATA, 32);
1371                NdisMoveMemory(pAd->StaCfg.GTK, GTK, 32);
1372                pAd->StaCfg.DefaultKeyId = peerKeyInfo.KeyIndex;
1373
1374                // Prepare pair-wise key information into shared key table
1375                NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
1376                pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
1377                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, GTK, LEN_TKIP_EK);
1378                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &GTK[16], LEN_TKIP_RXMICK);
1379                NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &GTK[24], LEN_TKIP_TXMICK);
1380
1381                // Update Shared Key CipherAlg
1382                pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
1383                if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
1384                        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
1385                else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
1386                        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
1387                else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
1388                        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64;
1389                else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
1390                        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128;
1391
1392        //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK);
1393        }
1394
1395        // Update group key information to ASIC Shared Key Table
1396        AsicAddSharedKeyEntry(pAd,
1397                                                  BSS0,
1398                                                  pAd->StaCfg.DefaultKeyId,
1399                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1400                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
1401                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
1402                                                  pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
1403
1404        // Update ASIC WCID attribute table and IVEIV table
1405        RTMPAddWcidAttributeEntry(pAd,
1406                                                          BSS0,
1407                                                          pAd->StaCfg.DefaultKeyId,
1408                                                          pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1409                                                          NULL);
1410
1411        // set 802.1x port control
1412        STA_PORT_SECURED(pAd);
1413
1414    // Indicate Connected for GUI
1415    pAd->IndicateMediaState = NdisMediaStateConnected;
1416
1417        // init header and Fill Packet
1418        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1419
1420        // Zero Group message 1 body
1421        NdisZeroMemory(&Packet, sizeof(Packet));
1422        Packet.ProVer   = EAPOL_VER;
1423        Packet.ProType  = EAPOLKey;
1424        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;                // No data field
1425
1426        //
1427        // Group Message 2 as  EAPOL-Key(1,0,0,0,G,0,0,MIC,0)
1428        //
1429        if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1430        {
1431                Packet.KeyDesc.Type = WPA2_KEY_DESC;
1432        }
1433        else
1434        {
1435                Packet.KeyDesc.Type = WPA1_KEY_DESC;
1436        }
1437
1438        // Key descriptor version and appropriate RSN IE
1439        Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
1440
1441        // Update Key Length
1442        Packet.KeyDesc.KeyLength[0] = pGroup->KeyDesc.KeyLength[0];
1443        Packet.KeyDesc.KeyLength[1] = pGroup->KeyDesc.KeyLength[1];
1444
1445        // Key Index as G-Msg 1
1446        if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
1447                Packet.KeyDesc.KeyInfo.KeyIndex = peerKeyInfo.KeyIndex;
1448
1449        // Key Type Group key
1450        Packet.KeyDesc.KeyInfo.KeyType = GROUPKEY;
1451
1452        // KeyMic field presented
1453        Packet.KeyDesc.KeyInfo.KeyMic  = 1;
1454
1455        // Secure bit
1456        Packet.KeyDesc.KeyInfo.Secure  = 1;
1457
1458        // Convert to little-endian format.
1459        *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
1460
1461        // Key Replay count
1462        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1463
1464        // Out buffer for transmitting group message 2
1465        MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
1466        if(pOutBuffer == NULL)
1467        {
1468                MlmeFreeMemory(pAd, (PUCHAR)mpool);
1469                return;
1470        }
1471
1472        // Prepare EAPOL frame for MIC calculation
1473        // Be careful, only EAPOL frame is counted for MIC calculation
1474        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1475                Packet.Body_Len[1] + 4,    &Packet,
1476                END_OF_ARGS);
1477
1478        // Prepare and Fill MIC value
1479        NdisZeroMemory(Mic, sizeof(Mic));
1480        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
1481        {
1482                // AES
1483                HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1484                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1485        }
1486        else
1487        {
1488                hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
1489        }
1490        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
1491
1492
1493        MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
1494                                                LENGTH_802_3,                   &Header802_3,
1495                                                Packet.Body_Len[1] + 4, &Packet,
1496                                                END_OF_ARGS);
1497
1498
1499        // 5. Copy frame to Tx ring and prepare for encryption
1500        RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE);
1501
1502        // 6 Free allocated memory
1503        MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
1504        os_free_mem(pAd, (PUCHAR)mpool);
1505
1506        // send wireless event - for set key done WPA2
1507        if (pAd->CommonCfg.bWirelessEvent)
1508                RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1509
1510        DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action <-----\n"));
1511}
1512
1513/*
1514        ========================================================================
1515
1516        Routine Description:
1517                Init WPA MAC header
1518
1519        Arguments:
1520                pAd     Pointer to our adapter
1521
1522        Return Value:
1523                None
1524
1525        Note:
1526
1527        ========================================================================
1528*/
1529VOID    WpaMacHeaderInit(
1530        IN              PRTMP_ADAPTER   pAd,
1531        IN OUT  PHEADER_802_11  pHdr80211,
1532        IN              UCHAR                   wep,
1533        IN              PUCHAR              pAddr1)
1534{
1535        NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
1536        pHdr80211->FC.Type      = BTYPE_DATA;
1537        pHdr80211->FC.ToDs      = 1;
1538        if (wep == 1)
1539                pHdr80211->FC.Wep = 1;
1540
1541         //     Addr1: BSSID, Addr2: SA, Addr3: DA
1542        COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1);
1543        COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
1544        COPY_MAC_ADDR(pHdr80211->Addr3, pAd->CommonCfg.Bssid);
1545        pHdr80211->Sequence =   pAd->Sequence;
1546}
1547
1548/*
1549        ========================================================================
1550
1551        Routine Description:
1552                Copy frame from waiting queue into relative ring buffer and set
1553        appropriate ASIC register to kick hardware encryption before really
1554        sent out to air.
1555
1556        Arguments:
1557                pAd             Pointer to our adapter
1558                PNDIS_PACKET    Pointer to outgoing Ndis frame
1559                NumberOfFrag    Number of fragment required
1560
1561        Return Value:
1562                None
1563
1564        Note:
1565
1566        ========================================================================
1567*/
1568VOID    RTMPToWirelessSta(
1569        IN      PRTMP_ADAPTER   pAd,
1570        IN  PUCHAR          pHeader802_3,
1571    IN  UINT            HdrLen,
1572        IN  PUCHAR          pData,
1573    IN  UINT            DataLen,
1574    IN  BOOLEAN                 is4wayFrame)
1575
1576{
1577        NDIS_STATUS     Status;
1578        PNDIS_PACKET    pPacket;
1579        UCHAR   Index;
1580
1581        do
1582        {
1583                // 1. build a NDIS packet and call RTMPSendPacket();
1584                //    be careful about how/when to release this internal allocated NDIS PACKET buffer
1585                Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
1586                if (Status != NDIS_STATUS_SUCCESS)
1587                        break;
1588
1589                if (is4wayFrame)
1590                        RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
1591                else
1592                        RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
1593
1594                // 2. send out the packet
1595                Status = STASendPacket(pAd, pPacket);
1596                if(Status == NDIS_STATUS_SUCCESS)
1597                {
1598                        // Dequeue one frame from TxSwQueue0..3 queue and process it
1599                        // There are three place calling dequeue for TX ring.
1600                        // 1. Here, right after queueing the frame.
1601                        // 2. At the end of TxRingTxDone service routine.
1602                        // 3. Upon NDIS call RTMPSendPackets
1603                        if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1604                                (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
1605                        {
1606                                for(Index = 0; Index < 5; Index ++)
1607                                        if(pAd->TxSwQueue[Index].Number > 0)
1608                                                RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS);
1609                        }
1610                }
1611        } while(FALSE);
1612
1613}
1614
1615/*
1616    ========================================================================
1617
1618    Routine Description:
1619    Check Sanity RSN IE form AP
1620
1621    Arguments:
1622
1623    Return Value:
1624
1625
1626    ========================================================================
1627*/
1628BOOLEAN CheckRSNIE(
1629        IN  PRTMP_ADAPTER   pAd,
1630        IN  PUCHAR          pData,
1631        IN  UCHAR           DataLen,
1632        OUT     UCHAR                   *Offset)
1633{
1634        PUCHAR              pVIE;
1635        UCHAR               len;
1636        PEID_STRUCT         pEid;
1637        BOOLEAN                         result = FALSE;
1638
1639        pVIE = pData;
1640        len      = DataLen;
1641        *Offset = 0;
1642
1643        while (len > sizeof(RSNIE2))
1644        {
1645                pEid = (PEID_STRUCT) pVIE;
1646                // WPA RSN IE
1647                if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
1648                {
1649                        if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) &&
1650                                (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) &&
1651                                (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2)))
1652                        {
1653                                        DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA/WPAPSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2)));
1654                                        result = TRUE;
1655                        }
1656
1657                        *Offset += (pEid->Len + 2);
1658                }
1659                // WPA2 RSN IE
1660                else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
1661                {
1662                        if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) &&
1663                                (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) &&
1664                                (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2)))
1665                        {
1666                                        DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2)));
1667                                        result = TRUE;
1668                        }
1669
1670                        *Offset += (pEid->Len + 2);
1671                }
1672                else
1673                {
1674                        break;
1675                }
1676
1677                pVIE += (pEid->Len + 2);
1678                len  -= (pEid->Len + 2);
1679        }
1680
1681        DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> skip_offset(%d) \n", *Offset));
1682
1683        return result;
1684
1685}
1686
1687
1688/*
1689    ========================================================================
1690
1691    Routine Description:
1692    Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
1693    GTK  is encaptulated in KDE format at  p.83 802.11i D10
1694
1695    Arguments:
1696
1697    Return Value:
1698
1699    Note:
1700        802.11i D10
1701
1702    ========================================================================
1703*/
1704BOOLEAN ParseKeyData(
1705        IN  PRTMP_ADAPTER   pAd,
1706        IN  PUCHAR          pKeyData,
1707        IN  UCHAR           KeyDataLen,
1708        IN      UCHAR                   bPairewise)
1709{
1710    PKDE_ENCAP          pKDE = NULL;
1711    PUCHAR              pMyKeyData = pKeyData;
1712    UCHAR               KeyDataLength = KeyDataLen;
1713    UCHAR               GTKLEN;
1714        UCHAR                           skip_offset;
1715
1716        // Verify The RSN IE contained in Pairewise-Msg 3 and skip it
1717        if (bPairewise)
1718    {
1719                // Check RSN IE whether it is WPA2/WPA2PSK
1720                if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset))
1721                {
1722                        DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n"));
1723                        hex_dump("Get KEYDATA :", pKeyData, KeyDataLen);
1724                        return FALSE;
1725        }
1726        else
1727                {
1728                        // skip RSN IE
1729                        pMyKeyData += skip_offset;
1730                        KeyDataLength -= skip_offset;
1731
1732                        //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1733                }
1734        }
1735
1736        DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1737
1738        // Parse EKD format
1739        if (KeyDataLength >= 8)
1740    {
1741        pKDE = (PKDE_ENCAP) pMyKeyData;
1742    }
1743        else
1744    {
1745                DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n"));
1746        return FALSE;
1747    }
1748
1749
1750        // Sanity check - shared key index should not be 0
1751        if (pKDE->GTKEncap.Kid == 0)
1752    {
1753        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n"));
1754        return FALSE;
1755    }
1756
1757        // Sanity check - KED length
1758        if (KeyDataLength < (pKDE->Len + 2))
1759    {
1760        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1761        return FALSE;
1762    }
1763
1764        // Get GTK length - refer to IEEE 802.11i-2004 p.82
1765        GTKLEN = pKDE->Len -6;
1766
1767        if (GTKLEN < LEN_AES_KEY)
1768        {
1769                DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1770        return FALSE;
1771        }
1772        else
1773                DBGPRINT(RT_DEBUG_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN));
1774
1775        // Update GTK
1776        // set key material, TxMic and RxMic for WPAPSK
1777        NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32);
1778        pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid;
1779
1780        // Update shared key table
1781        NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
1782        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
1783        NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK);
1784        NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK);
1785        NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK);
1786
1787        // Update Shared Key CipherAlg
1788        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
1789        if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
1790                pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
1791        else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
1792                pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
1793        else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
1794                pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64;
1795        else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
1796                pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128;
1797
1798        return TRUE;
1799
1800}
1801
1802/*
1803        ========================================================================
1804
1805        Routine Description:
1806                Cisco CCKM PRF function
1807
1808        Arguments:
1809                key                             Cisco Base Transient Key (BTK)
1810                key_len                 The key length of the BTK
1811                data                    Ruquest Number(RN) + BSSID
1812                data_len                The length of the data
1813                output                  Store for PTK(Pairwise transient keys)
1814                len                             The length of the output
1815        Return Value:
1816                None
1817
1818        Note:
1819                802.1i  Annex F.9
1820
1821        ========================================================================
1822*/
1823VOID CCKMPRF(
1824        IN      UCHAR   *key,
1825        IN      INT             key_len,
1826        IN      UCHAR   *data,
1827        IN      INT             data_len,
1828        OUT     UCHAR   *output,
1829        IN      INT             len)
1830{
1831        INT             i;
1832        UCHAR   input[1024];
1833        INT             currentindex = 0;
1834        INT             total_len;
1835
1836        NdisMoveMemory(input, data, data_len);
1837        total_len = data_len;
1838        input[total_len] = 0;
1839        total_len++;
1840        for     (i = 0; i <     (len + 19) / 20; i++)
1841        {
1842                HMAC_SHA1(input, total_len,     key, key_len, &output[currentindex]);
1843                currentindex += 20;
1844                input[total_len - 1]++;
1845        }
1846}
1847
1848/*
1849        ========================================================================
1850
1851        Routine Description:
1852                Process MIC error indication and record MIC error timer.
1853
1854        Arguments:
1855                pAd     Pointer to our adapter
1856                pWpaKey                 Pointer to the WPA key structure
1857
1858        Return Value:
1859                None
1860
1861        IRQL = DISPATCH_LEVEL
1862
1863        Note:
1864
1865        ========================================================================
1866*/
1867VOID    RTMPReportMicError(
1868        IN      PRTMP_ADAPTER   pAd,
1869        IN      PCIPHER_KEY     pWpaKey)
1870{
1871        ULONG   Now;
1872    UCHAR   unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0);
1873
1874        // Record Last MIC error time and count
1875        Now = jiffies;
1876        if (pAd->StaCfg.MicErrCnt == 0)
1877        {
1878                pAd->StaCfg.MicErrCnt++;
1879                pAd->StaCfg.LastMicErrorTime = Now;
1880        NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
1881        }
1882        else if (pAd->StaCfg.MicErrCnt == 1)
1883        {
1884                if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now)
1885                {
1886                        // Update Last MIC error time, this did not violate two MIC errors within 60 seconds
1887                        pAd->StaCfg.LastMicErrorTime = Now;
1888                }
1889                else
1890                {
1891
1892                        if (pAd->CommonCfg.bWirelessEvent)
1893                                RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1894
1895                        pAd->StaCfg.LastMicErrorTime = Now;
1896                        // Violate MIC error counts, MIC countermeasures kicks in
1897                        pAd->StaCfg.MicErrCnt++;
1898                }
1899        }
1900        else
1901        {
1902                // MIC error count >= 2
1903                // This should not happen
1904                ;
1905        }
1906    MlmeEnqueue(pAd,
1907                                MLME_CNTL_STATE_MACHINE,
1908                                OID_802_11_MIC_FAILURE_REPORT_FRAME,
1909                                1,
1910                                &unicastKey);
1911
1912    if (pAd->StaCfg.MicErrCnt == 2)
1913    {
1914        RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
1915    }
1916}
1917
1918#define LENGTH_EAP_H    4
1919// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).
1920INT         WpaCheckEapCode(
1921        IN  PRTMP_ADAPTER               pAd,
1922        IN  PUCHAR                              pFrame,
1923        IN  USHORT                              FrameLen,
1924        IN  USHORT                              OffSet)
1925{
1926
1927        PUCHAR  pData;
1928        INT     result = 0;
1929
1930        if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H )
1931                return result;
1932
1933        pData = pFrame + OffSet; // skip offset bytes
1934
1935        if(*(pData+1) == EAPPacket)     // 802.1x header - Packet Type
1936        {
1937                 result = *(pData+4);           // EAP header - Code
1938        }
1939
1940        return result;
1941}
1942
1943VOID    WpaSendMicFailureToWpaSupplicant(
1944    IN  PRTMP_ADAPTER    pAd,
1945    IN  BOOLEAN          bUnicast)
1946{
1947    union iwreq_data    wrqu;
1948    char custom[IW_CUSTOM_MAX] = {0};
1949
1950    sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
1951    if (bUnicast)
1952        sprintf(custom, "%s unicast", custom);
1953    wrqu.data.length = strlen(custom);
1954    wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
1955
1956    return;
1957}
1958
1959VOID    WpaMicFailureReportFrame(
1960        IN  PRTMP_ADAPTER   pAd,
1961        IN MLME_QUEUE_ELEM *Elem)
1962{
1963        PUCHAR              pOutBuffer = NULL;
1964        UCHAR               Header802_3[14];
1965        ULONG               FrameLen = 0;
1966        EAPOL_PACKET        Packet;
1967        UCHAR               Mic[16];
1968    BOOLEAN             bUnicast;
1969
1970        DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
1971
1972    bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE);
1973        pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
1974
1975        // init 802.3 header and Fill Packet
1976        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1977
1978        NdisZeroMemory(&Packet, sizeof(Packet));
1979        Packet.ProVer   = EAPOL_VER;
1980        Packet.ProType  = EAPOLKey;
1981
1982        Packet.KeyDesc.Type = WPA1_KEY_DESC;
1983
1984    // Request field presented
1985    Packet.KeyDesc.KeyInfo.Request = 1;
1986
1987        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
1988        {
1989                Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
1990        }
1991        else      // TKIP
1992        {
1993                Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
1994        }
1995
1996    Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
1997
1998        // KeyMic field presented
1999        Packet.KeyDesc.KeyInfo.KeyMic  = 1;
2000
2001    // Error field presented
2002        Packet.KeyDesc.KeyInfo.Error  = 1;
2003
2004        // Update packet length after decide Key data payload
2005        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;
2006
2007        // Key Replay Count
2008        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
2009    inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
2010
2011        // Convert to little-endian format.
2012        *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
2013
2014
2015        MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer);  // allocate memory
2016        if(pOutBuffer == NULL)
2017        {
2018                return;
2019        }
2020
2021        // Prepare EAPOL frame for MIC calculation
2022        // Be careful, only EAPOL frame is counted for MIC calculation
2023        MakeOutgoingFrame(pOutBuffer,               &FrameLen,
2024                              Packet.Body_Len[1] + 4,   &Packet,
2025                              END_OF_ARGS);
2026
2027        // Prepare and Fill MIC value
2028        NdisZeroMemory(Mic, sizeof(Mic));
2029        if(pAd->StaCfg.WepStatus  == Ndis802_11Encryption3Enabled)
2030        {       // AES
2031        UCHAR digest[20] = {0};
2032                HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
2033                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
2034        }
2035        else
2036        {       // TKIP
2037                hmac_md5(pAd->StaCfg.PTK,  LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
2038        }
2039        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
2040
2041    MakeOutgoingFrame(pOutBuffer,               &FrameLen,
2042                                LENGTH_802_3,                           &Header802_3,
2043                                Packet.Body_Len[1] + 4,     &Packet,
2044                                END_OF_ARGS);
2045
2046        // opy frame to Tx ring and send MIC failure report frame to authenticator
2047        RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE);
2048
2049        MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
2050
2051        DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
2052}
2053
2054/** from wpa_supplicant
2055 * inc_byte_array - Increment arbitrary length byte array by one
2056 * @counter: Pointer to byte array
2057 * @len: Length of the counter in bytes
2058 *
2059 * This function increments the last byte of the counter by one and continues
2060 * rolling over to more significant bytes if the byte was incremented from
2061 * 0xff to 0x00.
2062 */
2063void inc_byte_array(UCHAR *counter, int len)
2064{
2065        int pos = len - 1;
2066        while (pos >= 0) {
2067                counter[pos]++;
2068                if (counter[pos] != 0)
2069                        break;
2070                pos--;
2071        }
2072}
2073
2074VOID WpaDisassocApAndBlockAssoc(
2075    IN PVOID SystemSpecific1,
2076    IN PVOID FunctionContext,
2077    IN PVOID SystemSpecific2,
2078    IN PVOID SystemSpecific3)
2079{
2080    RTMP_ADAPTER                *pAd = (PRTMP_ADAPTER)FunctionContext;
2081    MLME_DISASSOC_REQ_STRUCT    DisassocReq;
2082
2083        // disassoc from current AP first
2084        DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
2085        DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE);
2086        MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
2087
2088        pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
2089        pAd->StaCfg.bBlockAssoc = TRUE;
2090}
2091
2092