linux/drivers/staging/rt2860/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#include "../rt_config.h"
  39// WPA OUI
  40UCHAR           OUI_WPA_NONE_AKM[4]             = {0x00, 0x50, 0xF2, 0x00};
  41UCHAR       OUI_WPA_VERSION[4]      = {0x00, 0x50, 0xF2, 0x01};
  42UCHAR       OUI_WPA_WEP40[4]      = {0x00, 0x50, 0xF2, 0x01};
  43UCHAR       OUI_WPA_TKIP[4]     = {0x00, 0x50, 0xF2, 0x02};
  44UCHAR       OUI_WPA_CCMP[4]     = {0x00, 0x50, 0xF2, 0x04};
  45UCHAR       OUI_WPA_WEP104[4]      = {0x00, 0x50, 0xF2, 0x05};
  46UCHAR       OUI_WPA_8021X_AKM[4]        = {0x00, 0x50, 0xF2, 0x01};
  47UCHAR       OUI_WPA_PSK_AKM[4]      = {0x00, 0x50, 0xF2, 0x02};
  48// WPA2 OUI
  49UCHAR       OUI_WPA2_WEP40[4]   = {0x00, 0x0F, 0xAC, 0x01};
  50UCHAR       OUI_WPA2_TKIP[4]        = {0x00, 0x0F, 0xAC, 0x02};
  51UCHAR       OUI_WPA2_CCMP[4]        = {0x00, 0x0F, 0xAC, 0x04};
  52UCHAR       OUI_WPA2_8021X_AKM[4]   = {0x00, 0x0F, 0xAC, 0x01};
  53UCHAR       OUI_WPA2_PSK_AKM[4]         = {0x00, 0x0F, 0xAC, 0x02};
  54UCHAR       OUI_WPA2_WEP104[4]   = {0x00, 0x0F, 0xAC, 0x05};
  55// MSA OUI
  56UCHAR           OUI_MSA_8021X_AKM[4]    = {0x00, 0x0F, 0xAC, 0x05};             // Not yet final - IEEE 802.11s-D1.06
  57UCHAR           OUI_MSA_PSK_AKM[4]      = {0x00, 0x0F, 0xAC, 0x06};             // Not yet final - IEEE 802.11s-D1.06
  58
  59/*
  60        ========================================================================
  61
  62        Routine Description:
  63                The pseudo-random function(PRF) that hashes various inputs to
  64                derive a pseudo-random value. To add liveness to the pseudo-random
  65                value, a nonce should be one of the inputs.
  66
  67                It is used to generate PTK, GTK or some specific random value.
  68
  69        Arguments:
  70                UCHAR   *key,           -       the key material for HMAC_SHA1 use
  71                INT             key_len         -       the length of key
  72                UCHAR   *prefix         -       a prefix label
  73                INT             prefix_len      -       the length of the label
  74                UCHAR   *data           -       a specific data with variable length
  75                INT             data_len        -       the length of a specific data
  76                INT             len                     -       the output lenght
  77
  78        Return Value:
  79                UCHAR   *output         -       the calculated result
  80
  81        Note:
  82                802.11i-2004    Annex H.3
  83
  84        ========================================================================
  85*/
  86VOID    PRF(
  87        IN      UCHAR   *key,
  88        IN      INT             key_len,
  89        IN      UCHAR   *prefix,
  90        IN      INT             prefix_len,
  91        IN      UCHAR   *data,
  92        IN      INT             data_len,
  93        OUT     UCHAR   *output,
  94        IN      INT             len)
  95{
  96        INT             i;
  97    UCHAR   *input;
  98        INT             currentindex = 0;
  99        INT             total_len;
 100
 101        // Allocate memory for input
 102        os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
 103
 104    if (input == NULL)
 105    {
 106        DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
 107        return;
 108    }
 109
 110        // Generate concatenation input
 111        NdisMoveMemory(input, prefix, prefix_len);
 112
 113        // Concatenate a single octet containing 0
 114        input[prefix_len] =     0;
 115
 116        // Concatenate specific data
 117        NdisMoveMemory(&input[prefix_len + 1], data, data_len);
 118        total_len =     prefix_len + 1 + data_len;
 119
 120        // Concatenate a single octet containing 0
 121        // This octet shall be update later
 122        input[total_len] = 0;
 123        total_len++;
 124
 125        // Iterate to calculate the result by hmac-sha-1
 126        // Then concatenate to last result
 127        for     (i = 0; i <     (len + 19) / 20; i++)
 128        {
 129                HMAC_SHA1(input, total_len,     key, key_len, &output[currentindex]);
 130                currentindex += 20;
 131
 132                // update the last octet
 133                input[total_len - 1]++;
 134        }
 135    os_free_mem(NULL, input);
 136}
 137
 138/*
 139        ========================================================================
 140
 141        Routine Description:
 142                It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
 143                It shall be called by 4-way handshake processing.
 144
 145        Arguments:
 146                pAd     -       pointer to our pAdapter context
 147                PMK             -       pointer to PMK
 148                ANonce  -       pointer to ANonce
 149                AA              -       pointer to Authenticator Address
 150                SNonce  -       pointer to SNonce
 151                SA              -       pointer to Supplicant Address
 152                len             -       indicate the length of PTK (octet)
 153
 154        Return Value:
 155                Output          pointer to the PTK
 156
 157        Note:
 158                Refer to IEEE 802.11i-2004 8.5.1.2
 159
 160        ========================================================================
 161*/
 162VOID WpaCountPTK(
 163        IN      PRTMP_ADAPTER   pAd,
 164        IN      UCHAR   *PMK,
 165        IN      UCHAR   *ANonce,
 166        IN      UCHAR   *AA,
 167        IN      UCHAR   *SNonce,
 168        IN      UCHAR   *SA,
 169        OUT     UCHAR   *output,
 170        IN      UINT    len)
 171{
 172        UCHAR   concatenation[76];
 173        UINT    CurrPos = 0;
 174        UCHAR   temp[32];
 175        UCHAR   Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
 176                                                'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
 177
 178        // initiate the concatenation input
 179        NdisZeroMemory(temp, sizeof(temp));
 180        NdisZeroMemory(concatenation, 76);
 181
 182        // Get smaller address
 183        if (RTMPCompareMemory(SA, AA, 6) == 1)
 184                NdisMoveMemory(concatenation, AA, 6);
 185        else
 186                NdisMoveMemory(concatenation, SA, 6);
 187        CurrPos += 6;
 188
 189        // Get larger address
 190        if (RTMPCompareMemory(SA, AA, 6) == 1)
 191                NdisMoveMemory(&concatenation[CurrPos], SA, 6);
 192        else
 193                NdisMoveMemory(&concatenation[CurrPos], AA, 6);
 194
 195        // store the larger mac address for backward compatible of
 196        // ralink proprietary STA-key issue
 197        NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
 198        CurrPos += 6;
 199
 200        // Get smaller Nonce
 201        if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
 202                NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
 203        else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
 204                NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
 205        else
 206                NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
 207        CurrPos += 32;
 208
 209        // Get larger Nonce
 210        if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
 211                NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
 212        else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
 213                NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
 214        else
 215                NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
 216        CurrPos += 32;
 217
 218        hex_dump("concatenation=", concatenation, 76);
 219
 220        // Use PRF to generate PTK
 221        PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
 222
 223}
 224
 225/*
 226        ========================================================================
 227
 228        Routine Description:
 229                Generate random number by software.
 230
 231        Arguments:
 232                pAd             -       pointer to our pAdapter context
 233                macAddr -       pointer to local MAC address
 234
 235        Return Value:
 236
 237        Note:
 238                802.1ii-2004  Annex H.5
 239
 240        ========================================================================
 241*/
 242VOID    GenRandom(
 243        IN      PRTMP_ADAPTER   pAd,
 244        IN      UCHAR                   *macAddr,
 245        OUT     UCHAR                   *random)
 246{
 247        INT             i, curr;
 248        UCHAR   local[80], KeyCounter[32];
 249        UCHAR   result[80];
 250        ULONG   CurrentTime;
 251        UCHAR   prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
 252
 253        // Zero the related information
 254        NdisZeroMemory(result, 80);
 255        NdisZeroMemory(local, 80);
 256        NdisZeroMemory(KeyCounter, 32);
 257
 258        for     (i = 0; i <     32;     i++)
 259        {
 260                // copy the local MAC address
 261                COPY_MAC_ADDR(local, macAddr);
 262                curr =  MAC_ADDR_LEN;
 263
 264                // concatenate the current time
 265                NdisGetSystemUpTime(&CurrentTime);
 266                NdisMoveMemory(&local[curr],  &CurrentTime,     sizeof(CurrentTime));
 267                curr += sizeof(CurrentTime);
 268
 269                // concatenate the last result
 270                NdisMoveMemory(&local[curr],  result, 32);
 271                curr += 32;
 272
 273                // concatenate a variable
 274                NdisMoveMemory(&local[curr],  &i,  2);
 275                curr += 2;
 276
 277                // calculate the result
 278                PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
 279        }
 280
 281        NdisMoveMemory(random, result,  32);
 282}
 283
 284/*
 285        ========================================================================
 286
 287        Routine Description:
 288                Build cipher suite in RSN-IE.
 289                It only shall be called by RTMPMakeRSNIE.
 290
 291        Arguments:
 292                pAd                     -       pointer to our pAdapter context
 293        ElementID       -       indicate the WPA1 or WPA2
 294        WepStatus       -       indicate the encryption type
 295                bMixCipher      -       a boolean to indicate the pairwise cipher and group
 296                                                cipher are the same or not
 297
 298        Return Value:
 299
 300        Note:
 301
 302        ========================================================================
 303*/
 304static VOID RTMPInsertRsnIeCipher(
 305        IN  PRTMP_ADAPTER   pAd,
 306        IN      UCHAR                   ElementID,
 307        IN      UINT                    WepStatus,
 308        IN      BOOLEAN                 bMixCipher,
 309        IN      UCHAR                   FlexibleCipher,
 310        OUT     PUCHAR                  pRsnIe,
 311        OUT     UCHAR                   *rsn_len)
 312{
 313        UCHAR   PairwiseCnt;
 314
 315        *rsn_len = 0;
 316
 317        // decide WPA2 or WPA1
 318        if (ElementID == Wpa2Ie)
 319        {
 320                RSNIE2  *pRsnie_cipher = (RSNIE2*)pRsnIe;
 321
 322                // Assign the verson as 1
 323                pRsnie_cipher->version = 1;
 324
 325        switch (WepStatus)
 326        {
 327                // TKIP mode
 328            case Ndis802_11Encryption2Enabled:
 329                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
 330                pRsnie_cipher->ucount = 1;
 331                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
 332                *rsn_len = sizeof(RSNIE2);
 333                break;
 334
 335                        // AES mode
 336            case Ndis802_11Encryption3Enabled:
 337                                if (bMixCipher)
 338                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
 339                                else
 340                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
 341                pRsnie_cipher->ucount = 1;
 342                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
 343                *rsn_len = sizeof(RSNIE2);
 344                break;
 345
 346                        // TKIP-AES mix mode
 347            case Ndis802_11Encryption4Enabled:
 348                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
 349
 350                                PairwiseCnt = 1;
 351                                // Insert WPA2 TKIP as the first pairwise cipher
 352                                if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
 353                                {
 354                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
 355                                        // Insert WPA2 AES as the secondary pairwise cipher
 356                                        if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
 357                                        {
 358                                NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
 359                                                PairwiseCnt = 2;
 360                                        }
 361                                }
 362                                else
 363                                {
 364                                        // Insert WPA2 AES as the first pairwise cipher
 365                                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
 366                                }
 367
 368                pRsnie_cipher->ucount = PairwiseCnt;
 369                *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
 370                break;
 371        }
 372
 373                if ((pAd->OpMode == OPMODE_STA) &&
 374                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
 375                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
 376                {
 377                        UINT GroupCipher = pAd->StaCfg.GroupCipher;
 378                        switch(GroupCipher)
 379                        {
 380                                case Ndis802_11GroupWEP40Enabled:
 381                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
 382                                        break;
 383                                case Ndis802_11GroupWEP104Enabled:
 384                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
 385                                        break;
 386                        }
 387                }
 388
 389                // swap for big-endian platform
 390                pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
 391            pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
 392        }
 393        else
 394        {
 395                RSNIE   *pRsnie_cipher = (RSNIE*)pRsnIe;
 396
 397                // Assign OUI and version
 398                NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
 399        pRsnie_cipher->version = 1;
 400
 401                switch (WepStatus)
 402                {
 403                        // TKIP mode
 404            case Ndis802_11Encryption2Enabled:
 405                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
 406                pRsnie_cipher->ucount = 1;
 407                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
 408                *rsn_len = sizeof(RSNIE);
 409                break;
 410
 411                        // AES mode
 412            case Ndis802_11Encryption3Enabled:
 413                                if (bMixCipher)
 414                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
 415                                else
 416                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
 417                pRsnie_cipher->ucount = 1;
 418                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
 419                *rsn_len = sizeof(RSNIE);
 420                break;
 421
 422                        // TKIP-AES mix mode
 423            case Ndis802_11Encryption4Enabled:
 424                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
 425
 426                                PairwiseCnt = 1;
 427                                // Insert WPA TKIP as the first pairwise cipher
 428                                if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
 429                                {
 430                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
 431                                        // Insert WPA AES as the secondary pairwise cipher
 432                                        if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
 433                                        {
 434                                NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
 435                                                PairwiseCnt = 2;
 436                                        }
 437                                }
 438                                else
 439                                {
 440                                        // Insert WPA AES as the first pairwise cipher
 441                                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
 442                                }
 443
 444                pRsnie_cipher->ucount = PairwiseCnt;
 445                *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
 446                break;
 447        }
 448
 449                if ((pAd->OpMode == OPMODE_STA) &&
 450                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
 451                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
 452                {
 453                        UINT GroupCipher = pAd->StaCfg.GroupCipher;
 454                        switch(GroupCipher)
 455                        {
 456                                case Ndis802_11GroupWEP40Enabled:
 457                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
 458                                        break;
 459                                case Ndis802_11GroupWEP104Enabled:
 460                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
 461                                        break;
 462                        }
 463                }
 464
 465                // swap for big-endian platform
 466                pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
 467            pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
 468        }
 469}
 470
 471/*
 472        ========================================================================
 473
 474        Routine Description:
 475                Build AKM suite in RSN-IE.
 476                It only shall be called by RTMPMakeRSNIE.
 477
 478        Arguments:
 479                pAd                     -       pointer to our pAdapter context
 480        ElementID       -       indicate the WPA1 or WPA2
 481        AuthMode        -       indicate the authentication mode
 482                apidx           -       indicate the interface index
 483
 484        Return Value:
 485
 486        Note:
 487
 488        ========================================================================
 489*/
 490static VOID RTMPInsertRsnIeAKM(
 491        IN  PRTMP_ADAPTER   pAd,
 492        IN      UCHAR                   ElementID,
 493        IN      UINT                    AuthMode,
 494        IN      UCHAR                   apidx,
 495        OUT     PUCHAR                  pRsnIe,
 496        OUT     UCHAR                   *rsn_len)
 497{
 498        RSNIE_AUTH              *pRsnie_auth;
 499
 500        pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
 501
 502        // decide WPA2 or WPA1
 503        if (ElementID == Wpa2Ie)
 504        {
 505                switch (AuthMode)
 506        {
 507            case Ndis802_11AuthModeWPA2:
 508            case Ndis802_11AuthModeWPA1WPA2:
 509                pRsnie_auth->acount = 1;
 510                        NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
 511                break;
 512
 513            case Ndis802_11AuthModeWPA2PSK:
 514            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
 515                pRsnie_auth->acount = 1;
 516                        NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
 517                break;
 518        }
 519        }
 520        else
 521        {
 522                switch (AuthMode)
 523        {
 524            case Ndis802_11AuthModeWPA:
 525            case Ndis802_11AuthModeWPA1WPA2:
 526                pRsnie_auth->acount = 1;
 527                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
 528                break;
 529
 530            case Ndis802_11AuthModeWPAPSK:
 531            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
 532                pRsnie_auth->acount = 1;
 533                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
 534                break;
 535
 536                        case Ndis802_11AuthModeWPANone:
 537                pRsnie_auth->acount = 1;
 538                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
 539                break;
 540        }
 541        }
 542
 543        pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
 544
 545        (*rsn_len) += sizeof(RSNIE_AUTH);       // update current RSNIE length
 546
 547}
 548
 549/*
 550        ========================================================================
 551
 552        Routine Description:
 553                Build capability in RSN-IE.
 554                It only shall be called by RTMPMakeRSNIE.
 555
 556        Arguments:
 557                pAd                     -       pointer to our pAdapter context
 558        ElementID       -       indicate the WPA1 or WPA2
 559                apidx           -       indicate the interface index
 560
 561        Return Value:
 562
 563        Note:
 564
 565        ========================================================================
 566*/
 567static VOID RTMPInsertRsnIeCap(
 568        IN  PRTMP_ADAPTER   pAd,
 569        IN      UCHAR                   ElementID,
 570        IN      UCHAR                   apidx,
 571        OUT     PUCHAR                  pRsnIe,
 572        OUT     UCHAR                   *rsn_len)
 573{
 574        RSN_CAPABILITIES    *pRSN_Cap;
 575
 576        // it could be ignored in WPA1 mode
 577        if (ElementID == WpaIe)
 578                return;
 579
 580        pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
 581
 582
 583        pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
 584
 585        (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
 586
 587}
 588
 589
 590/*
 591        ========================================================================
 592
 593        Routine Description:
 594                Build RSN IE context. It is not included element-ID and length.
 595
 596        Arguments:
 597                pAd                     -       pointer to our pAdapter context
 598        AuthMode        -       indicate the authentication mode
 599        WepStatus       -       indicate the encryption type
 600                apidx           -       indicate the interface index
 601
 602        Return Value:
 603
 604        Note:
 605
 606        ========================================================================
 607*/
 608VOID RTMPMakeRSNIE(
 609    IN  PRTMP_ADAPTER   pAd,
 610    IN  UINT            AuthMode,
 611    IN  UINT            WepStatus,
 612        IN      UCHAR                   apidx)
 613{
 614        PUCHAR          pRsnIe = NULL;                  // primary RSNIE
 615        UCHAR           *rsnielen_cur_p = 0;    // the length of the primary RSNIE
 616        UCHAR           *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
 617        UCHAR           PrimaryRsnie;
 618        BOOLEAN         bMixCipher = FALSE;     // indicate the pairwise and group cipher are different
 619        UCHAR           p_offset;
 620        WPA_MIX_PAIR_CIPHER             FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES;      // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
 621
 622        rsnielen_cur_p = NULL;
 623        rsnielen_ex_cur_p = NULL;
 624
 625        {
 626                {
 627                        if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
 628                        {
 629                                if (AuthMode < Ndis802_11AuthModeWPA)
 630                                        return;
 631                        }
 632                        else
 633                        {
 634                                // Support WPAPSK or WPA2PSK in STA-Infra mode
 635                                // Support WPANone in STA-Adhoc mode
 636                                if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
 637                                        (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
 638                                        (AuthMode != Ndis802_11AuthModeWPANone)
 639                                        )
 640                                        return;
 641                        }
 642
 643                        DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
 644
 645                        // Zero RSNIE context
 646                        pAd->StaCfg.RSNIE_Len = 0;
 647                        NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
 648
 649                        // Pointer to RSNIE
 650                        rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
 651                        pRsnIe = pAd->StaCfg.RSN_IE;
 652
 653                        bMixCipher = pAd->StaCfg.bMixCipher;
 654                }
 655        }
 656
 657        // indicate primary RSNIE as WPA or WPA2
 658        if ((AuthMode == Ndis802_11AuthModeWPA) ||
 659                (AuthMode == Ndis802_11AuthModeWPAPSK) ||
 660                (AuthMode == Ndis802_11AuthModeWPANone) ||
 661                (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
 662                (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
 663                PrimaryRsnie = WpaIe;
 664        else
 665                PrimaryRsnie = Wpa2Ie;
 666
 667        {
 668                // Build the primary RSNIE
 669                // 1. insert cipher suite
 670                RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
 671
 672                // 2. insert AKM
 673                RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
 674
 675                // 3. insert capability
 676                RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
 677        }
 678
 679        // 4. update the RSNIE length
 680        *rsnielen_cur_p = p_offset;
 681
 682        hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
 683
 684
 685}
 686
 687/*
 688    ==========================================================================
 689    Description:
 690                Check whether the received frame is EAP frame.
 691
 692        Arguments:
 693                pAd                             -       pointer to our pAdapter context
 694                pEntry                  -       pointer to active entry
 695                pData                   -       the received frame
 696                DataByteCount   -       the received frame's length
 697                FromWhichBSSID  -       indicate the interface index
 698
 699    Return:
 700         TRUE                   -       This frame is EAP frame
 701         FALSE                  -       otherwise
 702    ==========================================================================
 703*/
 704BOOLEAN RTMPCheckWPAframe(
 705    IN PRTMP_ADAPTER    pAd,
 706    IN PMAC_TABLE_ENTRY pEntry,
 707    IN PUCHAR           pData,
 708    IN ULONG            DataByteCount,
 709        IN UCHAR                        FromWhichBSSID)
 710{
 711        ULONG   Body_len;
 712        BOOLEAN Cancelled;
 713
 714
 715    if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
 716        return FALSE;
 717
 718
 719        // Skip LLC header
 720    if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
 721        // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
 722        NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
 723    {
 724        pData += 6;
 725    }
 726        // Skip 2-bytes EAPoL type
 727    if (NdisEqualMemory(EAPOL, pData, 2))
 728    {
 729        pData += 2;
 730    }
 731    else
 732        return FALSE;
 733
 734    switch (*(pData+1))
 735    {
 736        case EAPPacket:
 737                        Body_len = (*(pData+2)<<8) | (*(pData+3));
 738            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
 739            break;
 740        case EAPOLStart:
 741            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
 742                        if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
 743            {
 744                DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
 745                RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
 746                pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
 747            }
 748            break;
 749        case EAPOLLogoff:
 750            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
 751            break;
 752        case EAPOLKey:
 753                        Body_len = (*(pData+2)<<8) | (*(pData+3));
 754            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
 755            break;
 756        case EAPOLASFAlert:
 757            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
 758            break;
 759        default:
 760            return FALSE;
 761
 762    }
 763    return TRUE;
 764}
 765
 766/*
 767        ========================================================================
 768
 769        Routine Description:
 770                Misc function to decrypt AES body
 771
 772        Arguments:
 773
 774        Return Value:
 775
 776        Note:
 777                This function references to     RFC     3394 for aes key unwrap algorithm.
 778
 779        ========================================================================
 780*/
 781VOID    AES_GTK_KEY_UNWRAP(
 782        IN      UCHAR   *key,
 783        OUT     UCHAR   *plaintext,
 784        IN      UCHAR    c_len,
 785        IN      UCHAR   *ciphertext)
 786
 787{
 788        UCHAR       A[8], BIN[16], BOUT[16];
 789        UCHAR       xor;
 790        INT         i, j;
 791        aes_context aesctx;
 792        UCHAR       *R;
 793        INT         num_blocks = c_len/8;       // unit:64bits
 794
 795
 796        os_alloc_mem(NULL, (PUCHAR *)&R, 512);
 797
 798        if (R == NULL)
 799    {
 800        DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
 801        return;
 802    } /* End of if */
 803
 804        // Initialize
 805        NdisMoveMemory(A, ciphertext, 8);
 806        //Input plaintext
 807        for(i = 0; i < (c_len-8); i++)
 808        {
 809                R[ i] = ciphertext[i + 8];
 810        }
 811
 812        rtmp_aes_set_key(&aesctx, key, 128);
 813
 814        for(j = 5; j >= 0; j--)
 815        {
 816                for(i = (num_blocks-1); i > 0; i--)
 817                {
 818                        xor = (num_blocks -1 )* j + i;
 819                        NdisMoveMemory(BIN, A, 8);
 820                        BIN[7] = A[7] ^ xor;
 821                        NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
 822                        rtmp_aes_decrypt(&aesctx, BIN, BOUT);
 823                        NdisMoveMemory(A, &BOUT[0], 8);
 824                        NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
 825                }
 826        }
 827
 828        // OUTPUT
 829        for(i = 0; i < c_len; i++)
 830        {
 831                plaintext[i] = R[i];
 832        }
 833
 834
 835        os_free_mem(NULL, R);
 836}
 837
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.