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#ifdef CONFIG_STA_SUPPORT
 374                if ((pAd->OpMode == OPMODE_STA) &&
 375                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
 376                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
 377                {
 378                        UINT GroupCipher = pAd->StaCfg.GroupCipher;
 379                        switch(GroupCipher)
 380                        {
 381                                case Ndis802_11GroupWEP40Enabled:
 382                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
 383                                        break;
 384                                case Ndis802_11GroupWEP104Enabled:
 385                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
 386                                        break;
 387                        }
 388                }
 389#endif // CONFIG_STA_SUPPORT //
 390
 391                // swap for big-endian platform
 392                pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
 393            pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
 394        }
 395        else
 396        {
 397                RSNIE   *pRsnie_cipher = (RSNIE*)pRsnIe;
 398
 399                // Assign OUI and version
 400                NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
 401        pRsnie_cipher->version = 1;
 402
 403                switch (WepStatus)
 404                {
 405                        // TKIP mode
 406            case Ndis802_11Encryption2Enabled:
 407                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
 408                pRsnie_cipher->ucount = 1;
 409                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
 410                *rsn_len = sizeof(RSNIE);
 411                break;
 412
 413                        // AES mode
 414            case Ndis802_11Encryption3Enabled:
 415                                if (bMixCipher)
 416                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
 417                                else
 418                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
 419                pRsnie_cipher->ucount = 1;
 420                NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
 421                *rsn_len = sizeof(RSNIE);
 422                break;
 423
 424                        // TKIP-AES mix mode
 425            case Ndis802_11Encryption4Enabled:
 426                NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
 427
 428                                PairwiseCnt = 1;
 429                                // Insert WPA TKIP as the first pairwise cipher
 430                                if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
 431                                {
 432                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
 433                                        // Insert WPA AES as the secondary pairwise cipher
 434                                        if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
 435                                        {
 436                                NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
 437                                                PairwiseCnt = 2;
 438                                        }
 439                                }
 440                                else
 441                                {
 442                                        // Insert WPA AES as the first pairwise cipher
 443                                        NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
 444                                }
 445
 446                pRsnie_cipher->ucount = PairwiseCnt;
 447                *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
 448                break;
 449        }
 450
 451#ifdef CONFIG_STA_SUPPORT
 452                if ((pAd->OpMode == OPMODE_STA) &&
 453                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
 454                        (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
 455                {
 456                        UINT GroupCipher = pAd->StaCfg.GroupCipher;
 457                        switch(GroupCipher)
 458                        {
 459                                case Ndis802_11GroupWEP40Enabled:
 460                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
 461                                        break;
 462                                case Ndis802_11GroupWEP104Enabled:
 463                                        NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
 464                                        break;
 465                        }
 466                }
 467#endif // CONFIG_STA_SUPPORT //
 468
 469                // swap for big-endian platform
 470                pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
 471            pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
 472        }
 473}
 474
 475/*
 476        ========================================================================
 477
 478        Routine Description:
 479                Build AKM suite in RSN-IE.
 480                It only shall be called by RTMPMakeRSNIE.
 481
 482        Arguments:
 483                pAd                     -       pointer to our pAdapter context
 484        ElementID       -       indicate the WPA1 or WPA2
 485        AuthMode        -       indicate the authentication mode
 486                apidx           -       indicate the interface index
 487
 488        Return Value:
 489
 490        Note:
 491
 492        ========================================================================
 493*/
 494static VOID RTMPInsertRsnIeAKM(
 495        IN  PRTMP_ADAPTER   pAd,
 496        IN      UCHAR                   ElementID,
 497        IN      UINT                    AuthMode,
 498        IN      UCHAR                   apidx,
 499        OUT     PUCHAR                  pRsnIe,
 500        OUT     UCHAR                   *rsn_len)
 501{
 502        RSNIE_AUTH              *pRsnie_auth;
 503
 504        pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
 505
 506        // decide WPA2 or WPA1
 507        if (ElementID == Wpa2Ie)
 508        {
 509                switch (AuthMode)
 510        {
 511            case Ndis802_11AuthModeWPA2:
 512            case Ndis802_11AuthModeWPA1WPA2:
 513                pRsnie_auth->acount = 1;
 514                        NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
 515                break;
 516
 517            case Ndis802_11AuthModeWPA2PSK:
 518            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
 519                pRsnie_auth->acount = 1;
 520                        NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
 521                break;
 522        }
 523        }
 524        else
 525        {
 526                switch (AuthMode)
 527        {
 528            case Ndis802_11AuthModeWPA:
 529            case Ndis802_11AuthModeWPA1WPA2:
 530                pRsnie_auth->acount = 1;
 531                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
 532                break;
 533
 534            case Ndis802_11AuthModeWPAPSK:
 535            case Ndis802_11AuthModeWPA1PSKWPA2PSK:
 536                pRsnie_auth->acount = 1;
 537                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
 538                break;
 539
 540                        case Ndis802_11AuthModeWPANone:
 541                pRsnie_auth->acount = 1;
 542                NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
 543                break;
 544        }
 545        }
 546
 547        pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
 548
 549        (*rsn_len) += sizeof(RSNIE_AUTH);       // update current RSNIE length
 550
 551}
 552
 553/*
 554        ========================================================================
 555
 556        Routine Description:
 557                Build capability in RSN-IE.
 558                It only shall be called by RTMPMakeRSNIE.
 559
 560        Arguments:
 561                pAd                     -       pointer to our pAdapter context
 562        ElementID       -       indicate the WPA1 or WPA2
 563                apidx           -       indicate the interface index
 564
 565        Return Value:
 566
 567        Note:
 568
 569        ========================================================================
 570*/
 571static VOID RTMPInsertRsnIeCap(
 572        IN  PRTMP_ADAPTER   pAd,
 573        IN      UCHAR                   ElementID,
 574        IN      UCHAR                   apidx,
 575        OUT     PUCHAR                  pRsnIe,
 576        OUT     UCHAR                   *rsn_len)
 577{
 578        RSN_CAPABILITIES    *pRSN_Cap;
 579
 580        // it could be ignored in WPA1 mode
 581        if (ElementID == WpaIe)
 582                return;
 583
 584        pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
 585
 586
 587        pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
 588
 589        (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
 590
 591}
 592
 593
 594/*
 595        ========================================================================
 596
 597        Routine Description:
 598                Build RSN IE context. It is not included element-ID and length.
 599
 600        Arguments:
 601                pAd                     -       pointer to our pAdapter context
 602        AuthMode        -       indicate the authentication mode
 603        WepStatus       -       indicate the encryption type
 604                apidx           -       indicate the interface index
 605
 606        Return Value:
 607
 608        Note:
 609
 610        ========================================================================
 611*/
 612VOID RTMPMakeRSNIE(
 613    IN  PRTMP_ADAPTER   pAd,
 614    IN  UINT            AuthMode,
 615    IN  UINT            WepStatus,
 616        IN      UCHAR                   apidx)
 617{
 618        PUCHAR          pRsnIe = NULL;                  // primary RSNIE
 619        UCHAR           *rsnielen_cur_p = 0;    // the length of the primary RSNIE
 620        UCHAR           *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
 621        UCHAR           PrimaryRsnie;
 622        BOOLEAN         bMixCipher = FALSE;     // indicate the pairwise and group cipher are different
 623        UCHAR           p_offset;
 624        WPA_MIX_PAIR_CIPHER             FlexibleCipher = MIX_CIPHER_NOTUSE;     // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
 625
 626        rsnielen_cur_p = NULL;
 627        rsnielen_ex_cur_p = NULL;
 628
 629        {
 630#ifdef CONFIG_STA_SUPPORT
 631                IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
 632                {
 633#ifdef WPA_SUPPLICANT_SUPPORT
 634                        if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
 635                        {
 636                                if (AuthMode < Ndis802_11AuthModeWPA)
 637                                        return;
 638                        }
 639                        else
 640#endif // WPA_SUPPLICANT_SUPPORT //
 641                        {
 642                                // Support WPAPSK or WPA2PSK in STA-Infra mode
 643                                // Support WPANone in STA-Adhoc mode
 644                                if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
 645                                        (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
 646                                        (AuthMode != Ndis802_11AuthModeWPANone)
 647                                        )
 648                                        return;
 649                        }
 650
 651                        DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
 652
 653                        // Zero RSNIE context
 654                        pAd->StaCfg.RSNIE_Len = 0;
 655                        NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
 656
 657                        // Pointer to RSNIE
 658                        rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
 659                        pRsnIe = pAd->StaCfg.RSN_IE;
 660
 661                        bMixCipher = pAd->StaCfg.bMixCipher;
 662                }
 663#endif // CONFIG_STA_SUPPORT //
 664        }
 665
 666        // indicate primary RSNIE as WPA or WPA2
 667        if ((AuthMode == Ndis802_11AuthModeWPA) ||
 668                (AuthMode == Ndis802_11AuthModeWPAPSK) ||
 669                (AuthMode == Ndis802_11AuthModeWPANone) ||
 670                (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
 671                (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
 672                PrimaryRsnie = WpaIe;
 673        else
 674                PrimaryRsnie = Wpa2Ie;
 675
 676        {
 677                // Build the primary RSNIE
 678                // 1. insert cipher suite
 679                RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
 680
 681                // 2. insert AKM
 682                RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
 683
 684                // 3. insert capability
 685                RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
 686        }
 687
 688        // 4. update the RSNIE length
 689        *rsnielen_cur_p = p_offset;
 690
 691        hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
 692
 693
 694}
 695
 696/*
 697    ==========================================================================
 698    Description:
 699                Check whether the received frame is EAP frame.
 700
 701        Arguments:
 702                pAd                             -       pointer to our pAdapter context
 703                pEntry                  -       pointer to active entry
 704                pData                   -       the received frame
 705                DataByteCount   -       the received frame's length
 706                FromWhichBSSID  -       indicate the interface index
 707
 708    Return:
 709         TRUE                   -       This frame is EAP frame
 710         FALSE                  -       otherwise
 711    ==========================================================================
 712*/
 713BOOLEAN RTMPCheckWPAframe(
 714    IN PRTMP_ADAPTER    pAd,
 715    IN PMAC_TABLE_ENTRY pEntry,
 716    IN PUCHAR           pData,
 717    IN ULONG            DataByteCount,
 718        IN UCHAR                        FromWhichBSSID)
 719{
 720        ULONG   Body_len;
 721        BOOLEAN Cancelled;
 722
 723
 724    if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
 725        return FALSE;
 726
 727
 728        // Skip LLC header
 729    if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
 730        // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
 731        NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
 732    {
 733        pData += 6;
 734    }
 735        // Skip 2-bytes EAPoL type
 736    if (NdisEqualMemory(EAPOL, pData, 2))
 737    {
 738        pData += 2;
 739    }
 740    else
 741        return FALSE;
 742
 743    switch (*(pData+1))
 744    {
 745        case EAPPacket:
 746                        Body_len = (*(pData+2)<<8) | (*(pData+3));
 747            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
 748            break;
 749        case EAPOLStart:
 750            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
 751                        if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
 752            {
 753                DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
 754                RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
 755                pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
 756            }
 757            break;
 758        case EAPOLLogoff:
 759            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
 760            break;
 761        case EAPOLKey:
 762                        Body_len = (*(pData+2)<<8) | (*(pData+3));
 763            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
 764            break;
 765        case EAPOLASFAlert:
 766            DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
 767            break;
 768        default:
 769            return FALSE;
 770
 771    }
 772    return TRUE;
 773}
 774
 775
 776/*
 777    ==========================================================================
 778    Description:
 779        ENCRYPT AES GTK before sending in EAPOL frame.
 780        AES GTK length = 128 bit,  so fix blocks for aes-key-wrap as 2 in this function.
 781        This function references to RFC 3394 for aes key wrap algorithm.
 782    Return:
 783    ==========================================================================
 784*/
 785VOID AES_GTK_KEY_WRAP(
 786    IN UCHAR    *key,
 787    IN UCHAR    *plaintext,
 788    IN UCHAR    p_len,
 789    OUT UCHAR   *ciphertext)
 790{
 791    UCHAR       A[8], BIN[16], BOUT[16];
 792    UCHAR       R[512];
 793    INT         num_blocks = p_len/8;   // unit:64bits
 794    INT         i, j;
 795    aes_context aesctx;
 796    UCHAR       xor;
 797
 798    rtmp_aes_set_key(&aesctx, key, 128);
 799
 800    // Init IA
 801    for (i = 0; i < 8; i++)
 802        A[i] = 0xa6;
 803
 804    //Input plaintext
 805    for (i = 0; i < num_blocks; i++)
 806    {
 807        for (j = 0 ; j < 8; j++)
 808            R[8 * (i + 1) + j] = plaintext[8 * i + j];
 809    }
 810
 811    // Key Mix
 812    for (j = 0; j < 6; j++)
 813    {
 814        for(i = 1; i <= num_blocks; i++)
 815        {
 816            //phase 1
 817            NdisMoveMemory(BIN, A, 8);
 818            NdisMoveMemory(&BIN[8], &R[8 * i], 8);
 819            rtmp_aes_encrypt(&aesctx, BIN, BOUT);
 820
 821            NdisMoveMemory(A, &BOUT[0], 8);
 822            xor = num_blocks * j + i;
 823            A[7] = BOUT[7] ^ xor;
 824            NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
 825        }
 826    }
 827
 828    // Output ciphertext
 829    NdisMoveMemory(ciphertext, A, 8);
 830
 831    for (i = 1; i <= num_blocks; i++)
 832    {
 833        for (j = 0 ; j < 8; j++)
 834            ciphertext[8 * i + j] = R[8 * i + j];
 835    }
 836}
 837
 838
 839/*
 840        ========================================================================
 841
 842        Routine Description:
 843                Misc function to decrypt AES body
 844
 845        Arguments:
 846
 847        Return Value:
 848
 849        Note:
 850                This function references to     RFC     3394 for aes key unwrap algorithm.
 851
 852        ========================================================================
 853*/
 854VOID    AES_GTK_KEY_UNWRAP(
 855        IN      UCHAR   *key,
 856        OUT     UCHAR   *plaintext,
 857        IN      UCHAR    c_len,
 858        IN      UCHAR   *ciphertext)
 859
 860{
 861        UCHAR       A[8], BIN[16], BOUT[16];
 862        UCHAR       xor;
 863        INT         i, j;
 864        aes_context aesctx;
 865        UCHAR       *R;
 866        INT         num_blocks = c_len/8;       // unit:64bits
 867
 868
 869        os_alloc_mem(NULL, (PUCHAR *)&R, 512);
 870
 871        if (R == NULL)
 872    {
 873        DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
 874        return;
 875    } /* End of if */
 876
 877        // Initialize
 878        NdisMoveMemory(A, ciphertext, 8);
 879        //Input plaintext
 880        for(i = 0; i < (c_len-8); i++)
 881        {
 882                R[ i] = ciphertext[i + 8];
 883        }
 884
 885        rtmp_aes_set_key(&aesctx, key, 128);
 886
 887        for(j = 5; j >= 0; j--)
 888        {
 889                for(i = (num_blocks-1); i > 0; i--)
 890                {
 891                        xor = (num_blocks -1 )* j + i;
 892                        NdisMoveMemory(BIN, A, 8);
 893                        BIN[7] = A[7] ^ xor;
 894                        NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
 895                        rtmp_aes_decrypt(&aesctx, BIN, BOUT);
 896                        NdisMoveMemory(A, &BOUT[0], 8);
 897                        NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
 898                }
 899        }
 900
 901        // OUTPUT
 902        for(i = 0; i < c_len; i++)
 903        {
 904                plaintext[i] = R[i];
 905        }
 906
 907
 908        os_free_mem(NULL, R);
 909}
 910
 911/*
 912    ==========================================================================
 913    Description:
 914                Report the EAP message type
 915
 916        Arguments:
 917                msg             -       EAPOL_PAIR_MSG_1
 918                                        EAPOL_PAIR_MSG_2
 919                                        EAPOL_PAIR_MSG_3
 920                                        EAPOL_PAIR_MSG_4
 921                                        EAPOL_GROUP_MSG_1
 922                                        EAPOL_GROUP_MSG_2
 923
 924    Return:
 925         message type string
 926
 927    ==========================================================================
 928*/
 929CHAR *GetEapolMsgType(CHAR msg)
 930{
 931    if(msg == EAPOL_PAIR_MSG_1)
 932        return "Pairwise Message 1";
 933    else if(msg == EAPOL_PAIR_MSG_2)
 934        return "Pairwise Message 2";
 935        else if(msg == EAPOL_PAIR_MSG_3)
 936        return "Pairwise Message 3";
 937        else if(msg == EAPOL_PAIR_MSG_4)
 938        return "Pairwise Message 4";
 939        else if(msg == EAPOL_GROUP_MSG_1)
 940        return "Group Message 1";
 941        else if(msg == EAPOL_GROUP_MSG_2)
 942        return "Group Message 2";
 943    else
 944        return "Invalid Message";
 945}
 946
 947
 948/*
 949    ========================================================================
 950
 951    Routine Description:
 952    Check Sanity RSN IE of EAPoL message
 953
 954    Arguments:
 955
 956    Return Value:
 957
 958
 959    ========================================================================
 960*/
 961BOOLEAN RTMPCheckRSNIE(
 962        IN  PRTMP_ADAPTER   pAd,
 963        IN  PUCHAR          pData,
 964        IN  UCHAR           DataLen,
 965        IN  MAC_TABLE_ENTRY *pEntry,
 966        OUT     UCHAR                   *Offset)
 967{
 968        PUCHAR              pVIE;
 969        UCHAR               len;
 970        PEID_STRUCT         pEid;
 971        BOOLEAN                         result = FALSE;
 972
 973        pVIE = pData;
 974        len      = DataLen;
 975        *Offset = 0;
 976
 977        while (len > sizeof(RSNIE2))
 978        {
 979                pEid = (PEID_STRUCT) pVIE;
 980                // WPA RSN IE
 981                if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
 982                {
 983                        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
 984                                (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
 985                                (pEntry->RSNIE_Len == (pEid->Len + 2)))
 986                        {
 987                                        result = TRUE;
 988                        }
 989
 990                        *Offset += (pEid->Len + 2);
 991                }
 992                // WPA2 RSN IE
 993                else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
 994                {
 995                        if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
 996                                (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
 997                                (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
 998                        {
 999                                        result = TRUE;
1000                        }
1001
1002                        *Offset += (pEid->Len + 2);
1003                }
1004                else
1005                {
1006                        break;
1007                }
1008
1009                pVIE += (pEid->Len + 2);
1010                len  -= (pEid->Len + 2);
1011        }
1012
1013
1014        return result;
1015
1016}
1017
1018
1019/*
1020    ========================================================================
1021
1022    Routine Description:
1023    Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
1024    GTK  is encaptulated in KDE format at  p.83 802.11i D10
1025
1026    Arguments:
1027
1028    Return Value:
1029
1030    Note:
1031        802.11i D10
1032
1033    ========================================================================
1034*/
1035BOOLEAN RTMPParseEapolKeyData(
1036        IN  PRTMP_ADAPTER   pAd,
1037        IN  PUCHAR          pKeyData,
1038        IN  UCHAR           KeyDataLen,
1039        IN      UCHAR                   GroupKeyIndex,
1040        IN      UCHAR                   MsgType,
1041        IN      BOOLEAN                 bWPA2,
1042        IN  MAC_TABLE_ENTRY *pEntry)
1043{
1044    PKDE_ENCAP          pKDE = NULL;
1045    PUCHAR              pMyKeyData = pKeyData;
1046    UCHAR               KeyDataLength = KeyDataLen;
1047    UCHAR               GTKLEN = 0;
1048        UCHAR                           DefaultIdx = 0;
1049        UCHAR                           skip_offset;
1050
1051        // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
1052        if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
1053    {
1054                // Check RSN IE whether it is WPA2/WPA2PSK
1055                if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
1056                {
1057                        // send wireless event - for RSN IE different
1058                        if (pAd->CommonCfg.bWirelessEvent)
1059                                RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1060
1061                DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
1062                        hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
1063                        hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
1064
1065                        return FALSE;
1066        }
1067        else
1068                {
1069                        if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
1070                        {
1071                                // skip RSN IE
1072                                pMyKeyData += skip_offset;
1073                                KeyDataLength -= skip_offset;
1074                                DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1075                        }
1076                        else
1077                                return TRUE;
1078                }
1079        }
1080
1081        DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1082
1083        // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
1084        if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
1085        {
1086                if (KeyDataLength >= 8) // KDE format exclude GTK length
1087        {
1088                pKDE = (PKDE_ENCAP) pMyKeyData;
1089
1090
1091                        DefaultIdx = pKDE->GTKEncap.Kid;
1092
1093                        // Sanity check - KED length
1094                        if (KeyDataLength < (pKDE->Len + 2))
1095                {
1096                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1097                        return FALSE;
1098                }
1099
1100                        // Get GTK length - refer to IEEE 802.11i-2004 p.82
1101                        GTKLEN = pKDE->Len -6;
1102                        if (GTKLEN < LEN_AES_KEY)
1103                        {
1104                                DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1105                        return FALSE;
1106                        }
1107
1108        }
1109                else
1110        {
1111                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
1112                return FALSE;
1113        }
1114
1115                DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
1116                // skip it
1117                pMyKeyData += 8;
1118                KeyDataLength -= 8;
1119
1120        }
1121        else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
1122        {
1123                DefaultIdx = GroupKeyIndex;
1124                DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
1125        }
1126
1127        // Sanity check - shared key index must be 1 ~ 3
1128        if (DefaultIdx < 1 || DefaultIdx > 3)
1129    {
1130        DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1131        return FALSE;
1132    }
1133
1134
1135#ifdef CONFIG_STA_SUPPORT
1136        // Todo
1137#endif // CONFIG_STA_SUPPORT //
1138
1139        return TRUE;
1140
1141}
1142
1143
1144/*
1145        ========================================================================
1146
1147        Routine Description:
1148                Construct EAPoL message for WPA handshaking
1149                Its format is below,
1150
1151                +--------------------+
1152                | Protocol Version       |  1 octet
1153                +--------------------+
1154                | Protocol Type          |      1 octet
1155                +--------------------+
1156                | Body Length            |  2 octets
1157                +--------------------+
1158                | Descriptor Type        |      1 octet
1159                +--------------------+
1160                | Key Information    |  2 octets
1161                +--------------------+
1162                | Key Length         |  1 octet
1163                +--------------------+
1164                | Key Repaly Counter |  8 octets
1165                +--------------------+
1166                | Key Nonce                  |  32 octets
1167                +--------------------+
1168                | Key IV                         |  16 octets
1169                +--------------------+
1170                | Key RSC                        |  8 octets
1171                +--------------------+
1172                | Key ID or Reserved |  8 octets
1173                +--------------------+
1174                | Key MIC                        |      16 octets
1175                +--------------------+
1176                | Key Data Length        |      2 octets
1177                +--------------------+
1178                | Key Data                       |      n octets
1179                +--------------------+
1180
1181
1182        Arguments:
1183                pAd                     Pointer to our adapter
1184
1185        Return Value:
1186                None
1187
1188        Note:
1189
1190        ========================================================================
1191*/
1192VOID    ConstructEapolMsg(
1193        IN      PRTMP_ADAPTER           pAd,
1194    IN  UCHAR                           AuthMode,
1195    IN  UCHAR                           WepStatus,
1196    IN  UCHAR                           GroupKeyWepStatus,
1197    IN  UCHAR                           MsgType,
1198    IN  UCHAR                           DefaultKeyIdx,
1199    IN  UCHAR                           *ReplayCounter,
1200        IN      UCHAR                           *KeyNonce,
1201        IN      UCHAR                           *TxRSC,
1202        IN      UCHAR                           *PTK,
1203        IN      UCHAR                           *GTK,
1204        IN      UCHAR                           *RSNIE,
1205        IN      UCHAR                           RSNIE_Len,
1206    OUT PEAPOL_PACKET       pMsg)
1207{
1208        BOOLEAN bWPA2 = FALSE;
1209
1210        // Choose WPA2 or not
1211        if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
1212                bWPA2 = TRUE;
1213
1214    // Init Packet and Fill header
1215    pMsg->ProVer = EAPOL_VER;
1216    pMsg->ProType = EAPOLKey;
1217
1218        // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
1219        pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
1220
1221        // Fill in EAPoL descriptor
1222        if (bWPA2)
1223                pMsg->KeyDesc.Type = WPA2_KEY_DESC;
1224        else
1225                pMsg->KeyDesc.Type = WPA1_KEY_DESC;
1226
1227        // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
1228        // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
1229        pMsg->KeyDesc.KeyInfo.KeyDescVer =
1230                (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1231
1232        // Specify Key Type as Group(0) or Pairwise(1)
1233        if (MsgType >= EAPOL_GROUP_MSG_1)
1234                pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
1235        else
1236                pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1237
1238        // Specify Key Index, only group_msg1_WPA1
1239        if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
1240                pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
1241
1242        if (MsgType == EAPOL_PAIR_MSG_3)
1243                pMsg->KeyDesc.KeyInfo.Install = 1;
1244
1245        if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
1246                pMsg->KeyDesc.KeyInfo.KeyAck = 1;
1247
1248        if (MsgType != EAPOL_PAIR_MSG_1)
1249                pMsg->KeyDesc.KeyInfo.KeyMic = 1;
1250
1251        if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
1252    {
1253        pMsg->KeyDesc.KeyInfo.Secure = 1;
1254    }
1255
1256        if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1257    {
1258        pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
1259    }
1260
1261        // key Information element has done.
1262        *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
1263
1264        // Fill in Key Length
1265        {
1266                if (MsgType >= EAPOL_GROUP_MSG_1)
1267                {
1268                        // the length of group key cipher
1269                        pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
1270                }
1271                else
1272                {
1273                        // the length of pairwise key cipher
1274                        pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
1275                }
1276        }
1277
1278        // Fill in replay counter
1279    NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
1280
1281        // Fill Key Nonce field
1282        // ANonce : pairwise_msg1 & pairwise_msg3
1283        // SNonce : pairwise_msg2
1284        // GNonce : group_msg1_wpa1
1285        if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
1286        NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
1287
1288        // Fill key IV - WPA2 as 0, WPA1 as random
1289        if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
1290        {
1291                // Suggest IV be random number plus some number,
1292                NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
1293        pMsg->KeyDesc.KeyIv[15] += 2;
1294        }
1295
1296    // Fill Key RSC field
1297    // It contains the RSC for the GTK being installed.
1298        if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
1299        {
1300        NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
1301        }
1302
1303        // Clear Key MIC field for MIC calculation later
1304    NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1305
1306        ConstructEapolKeyData(pAd,
1307                                                  AuthMode,
1308                                                  WepStatus,
1309                                                  GroupKeyWepStatus,
1310                                                  MsgType,
1311                                                  DefaultKeyIdx,
1312                                                  bWPA2,
1313                                                  PTK,
1314                                                  GTK,
1315                                                  RSNIE,
1316                                                  RSNIE_Len,
1317                                                  pMsg);
1318
1319        // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
1320        if (MsgType != EAPOL_PAIR_MSG_1)
1321        {
1322                CalculateMIC(pAd, WepStatus, PTK, pMsg);
1323        }
1324
1325        DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1326        DBGPRINT(RT_DEBUG_TRACE, ("          Body length = %d \n", pMsg->Body_Len[1]));
1327        DBGPRINT(RT_DEBUG_TRACE, ("          Key length  = %d \n", pMsg->KeyDesc.KeyLength[1]));
1328
1329
1330}
1331
1332/*
1333        ========================================================================
1334
1335        Routine Description:
1336                Construct the Key Data field of EAPoL message
1337
1338        Arguments:
1339                pAd                     Pointer to our adapter
1340                Elem            Message body
1341
1342        Return Value:
1343                None
1344
1345        Note:
1346
1347        ========================================================================
1348*/
1349VOID    ConstructEapolKeyData(
1350        IN      PRTMP_ADAPTER   pAd,
1351        IN      UCHAR                   AuthMode,
1352        IN      UCHAR                   WepStatus,
1353        IN      UCHAR                   GroupKeyWepStatus,
1354        IN      UCHAR                   MsgType,
1355        IN      UCHAR                   DefaultKeyIdx,
1356        IN      BOOLEAN                 bWPA2Capable,
1357        IN      UCHAR                   *PTK,
1358        IN      UCHAR                   *GTK,
1359        IN      UCHAR                   *RSNIE,
1360        IN      UCHAR                   RSNIE_LEN,
1361        OUT PEAPOL_PACKET   pMsg)
1362{
1363        UCHAR           *mpool, *Key_Data, *Rc4GTK;
1364        UCHAR       ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
1365        UCHAR           data_offset;
1366
1367
1368        if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
1369                return;
1370
1371        // allocate memory pool
1372        os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
1373
1374    if (mpool == NULL)
1375                return;
1376
1377        /* Rc4GTK Len = 512 */
1378        Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
1379        /* Key_Data Len = 512 */
1380        Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
1381
1382        NdisZeroMemory(Key_Data, 512);
1383        pMsg->KeyDesc.KeyDataLen[1] = 0;
1384        data_offset = 0;
1385
1386        // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
1387        if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
1388        {
1389                if (bWPA2Capable)
1390                        Key_Data[data_offset + 0] = IE_WPA2;
1391                else
1392                        Key_Data[data_offset + 0] = IE_WPA;
1393
1394        Key_Data[data_offset + 1] = RSNIE_LEN;
1395                NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
1396                data_offset += (2 + RSNIE_LEN);
1397        }
1398
1399        // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
1400        if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1401        {
1402                // Key Data Encapsulation (KDE) format - 802.11i-2004  Figure-43w and Table-20h
1403        Key_Data[data_offset + 0] = 0xDD;
1404
1405                if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1406                {
1407                        Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
1408                }
1409                else
1410                {
1411                        Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
1412                }
1413
1414        Key_Data[data_offset + 2] = 0x00;
1415        Key_Data[data_offset + 3] = 0x0F;
1416        Key_Data[data_offset + 4] = 0xAC;
1417        Key_Data[data_offset + 5] = 0x01;
1418
1419                // GTK KDE format - 802.11i-2004  Figure-43x
1420        Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
1421        Key_Data[data_offset + 7] = 0x00;       // Reserved Byte
1422
1423                data_offset += 8;
1424        }
1425
1426
1427        // Encapsulate GTK and encrypt the key-data field with KEK.
1428        // Only for pairwise_msg3_WPA2 and group_msg1
1429        if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
1430        {
1431                // Fill in GTK
1432                if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1433                {
1434                        NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
1435                        data_offset += LEN_AES_KEY;
1436                }
1437                else
1438                {
1439                        NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
1440                        data_offset += TKIP_GTK_LENGTH;
1441                }
1442
1443                // Still dont know why, but if not append will occur "GTK not include in MSG3"
1444                // Patch for compatibility between zero config and funk
1445                if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
1446                {
1447                        if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1448                        {
1449                                Key_Data[data_offset + 0] = 0xDD;
1450                                Key_Data[data_offset + 1] = 0;
1451                                data_offset += 2;
1452                        }
1453                        else
1454                        {
1455                                Key_Data[data_offset + 0] = 0xDD;
1456                                Key_Data[data_offset + 1] = 0;
1457                                Key_Data[data_offset + 2] = 0;
1458                                Key_Data[data_offset + 3] = 0;
1459                                Key_Data[data_offset + 4] = 0;
1460                                Key_Data[data_offset + 5] = 0;
1461                                data_offset += 6;
1462                        }
1463                }
1464
1465                // Encrypt the data material in key data field
1466                if (WepStatus == Ndis802_11Encryption3Enabled)
1467                {
1468                        AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
1469            // AES wrap function will grow 8 bytes in length
1470            data_offset += 8;
1471                }
1472                else
1473                {
1474                        // PREPARE Encrypted  "Key DATA" field.  (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
1475                        // put TxTsc in Key RSC field
1476                        pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32;   //Init crc32.
1477
1478                        // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
1479                        NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
1480                        NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
1481                        ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey));  //INIT SBOX, KEYLEN+3(IV)
1482                        pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
1483                        WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
1484                }
1485
1486                NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
1487        }
1488        else
1489        {
1490                NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
1491        }
1492
1493        // set key data length field and total length
1494        pMsg->KeyDesc.KeyDataLen[1] = data_offset;
1495    pMsg->Body_Len[1] += data_offset;
1496
1497        os_free_mem(pAd, mpool);
1498
1499}
1500
1501/*
1502        ========================================================================
1503
1504        Routine Description:
1505                Calcaulate MIC. It is used during 4-ways handsharking.
1506
1507        Arguments:
1508                pAd                             -       pointer to our pAdapter context
1509        PeerWepStatus   -       indicate the encryption type
1510
1511        Return Value:
1512
1513        Note:
1514
1515        ========================================================================
1516*/
1517VOID    CalculateMIC(
1518        IN      PRTMP_ADAPTER   pAd,
1519        IN      UCHAR                   PeerWepStatus,
1520        IN      UCHAR                   *PTK,
1521        OUT PEAPOL_PACKET   pMsg)
1522{
1523    UCHAR   *OutBuffer;
1524        ULONG   FrameLen = 0;
1525        UCHAR   mic[LEN_KEY_DESC_MIC];
1526        UCHAR   digest[80];
1527
1528        // allocate memory for MIC calculation
1529        os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
1530
1531    if (OutBuffer == NULL)
1532    {
1533                DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
1534                return;
1535    }
1536
1537        // make a frame for calculating MIC.
1538    MakeOutgoingFrame(OutBuffer,                &FrameLen,
1539                      pMsg->Body_Len[1] + 4,    pMsg,
1540                      END_OF_ARGS);
1541
1542        NdisZeroMemory(mic, sizeof(mic));
1543
1544        // Calculate MIC
1545    if (PeerWepStatus == Ndis802_11Encryption3Enabled)
1546        {
1547                HMAC_SHA1(OutBuffer,  FrameLen, PTK, LEN_EAP_MICK, digest);
1548                NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
1549        }
1550        else
1551        {
1552                hmac_md5(PTK,  LEN_EAP_MICK, OutBuffer, FrameLen, mic);
1553        }
1554
1555        // store the calculated MIC
1556        NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
1557
1558        os_free_mem(pAd, OutBuffer);
1559}
1560
1561/*
1562        ========================================================================
1563
1564        Routine Description:
1565                Some received frames can't decrypt by Asic, so decrypt them by software.
1566
1567        Arguments:
1568                pAd                             -       pointer to our pAdapter context
1569        PeerWepStatus   -       indicate the encryption type
1570
1571        Return Value:
1572                NDIS_STATUS_SUCCESS             -       decryption successful
1573                NDIS_STATUS_FAILURE             -       decryption failure
1574
1575        ========================================================================
1576*/
1577NDIS_STATUS     RTMPSoftDecryptBroadCastData(
1578        IN      PRTMP_ADAPTER                                   pAd,
1579        IN      RX_BLK                                                  *pRxBlk,
1580        IN  NDIS_802_11_ENCRYPTION_STATUS       GroupCipher,
1581        IN  PCIPHER_KEY                                         pShard_key)
1582{
1583        PRXWI_STRUC                     pRxWI = pRxBlk->pRxWI;
1584
1585
1586
1587        // handle WEP decryption
1588        if (GroupCipher == Ndis802_11Encryption1Enabled)
1589    {
1590                if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
1591                {
1592
1593                        //Minus IV[4] & ICV[4]
1594                        pRxWI->MPDUtotalByteCount -= 8;
1595                }
1596                else
1597                {
1598                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
1599                        // give up this frame
1600                        return NDIS_STATUS_FAILURE;
1601                }
1602        }
1603        // handle TKIP decryption
1604        else if (GroupCipher == Ndis802_11Encryption2Enabled)
1605        {
1606                if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
1607                {
1608
1609                        //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
1610                        pRxWI->MPDUtotalByteCount -= 20;
1611                }
1612        else
1613                {
1614                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
1615                        // give up this frame
1616                        return NDIS_STATUS_FAILURE;
1617        }
1618        }
1619        // handle AES decryption
1620        else if (GroupCipher == Ndis802_11Encryption3Enabled)
1621        {
1622                if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
1623                {
1624
1625                        //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
1626                        pRxWI->MPDUtotalByteCount -= 16;
1627                }
1628                else
1629                {
1630                        DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
1631                        // give up this frame
1632                        return NDIS_STATUS_FAILURE;
1633                }
1634        }
1635        else
1636        {
1637                // give up this frame
1638                return NDIS_STATUS_FAILURE;
1639        }
1640
1641        return NDIS_STATUS_SUCCESS;
1642
1643}
1644
1645
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.