Staging: rt3070: remove dead CONFIG_APSTA_MIXED_SUPPORT code
[pandora-kernel.git] / drivers / staging / rt3070 / common / cmm_wpa.c
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
40 UCHAR           OUI_WPA_NONE_AKM[4]             = {0x00, 0x50, 0xF2, 0x00};
41 UCHAR       OUI_WPA_VERSION[4]      = {0x00, 0x50, 0xF2, 0x01};
42 UCHAR       OUI_WPA_TKIP[4]     = {0x00, 0x50, 0xF2, 0x02};
43 UCHAR       OUI_WPA_CCMP[4]     = {0x00, 0x50, 0xF2, 0x04};
44 UCHAR       OUI_WPA_8021X_AKM[4]        = {0x00, 0x50, 0xF2, 0x01};
45 UCHAR       OUI_WPA_PSK_AKM[4]      = {0x00, 0x50, 0xF2, 0x02};
46 // WPA2 OUI
47 UCHAR       OUI_WPA2_WEP40[4]   = {0x00, 0x0F, 0xAC, 0x01};
48 UCHAR       OUI_WPA2_TKIP[4]        = {0x00, 0x0F, 0xAC, 0x02};
49 UCHAR       OUI_WPA2_CCMP[4]        = {0x00, 0x0F, 0xAC, 0x04};
50 UCHAR       OUI_WPA2_8021X_AKM[4]   = {0x00, 0x0F, 0xAC, 0x01};
51 UCHAR       OUI_WPA2_PSK_AKM[4]         = {0x00, 0x0F, 0xAC, 0x02};
52 // MSA OUI
53 UCHAR           OUI_MSA_8021X_AKM[4]    = {0x00, 0x0F, 0xAC, 0x05};             // Not yet final - IEEE 802.11s-D1.06
54 UCHAR           OUI_MSA_PSK_AKM[4]      = {0x00, 0x0F, 0xAC, 0x06};             // Not yet final - IEEE 802.11s-D1.06
55
56 /*
57         ========================================================================
58
59         Routine Description:
60                 The pseudo-random function(PRF) that hashes various inputs to
61                 derive a pseudo-random value. To add liveness to the pseudo-random
62                 value, a nonce should be one of the inputs.
63
64                 It is used to generate PTK, GTK or some specific random value.
65
66         Arguments:
67                 UCHAR   *key,           -       the key material for HMAC_SHA1 use
68                 INT             key_len         -       the length of key
69                 UCHAR   *prefix         -       a prefix label
70                 INT             prefix_len      -       the length of the label
71                 UCHAR   *data           -       a specific data with variable length
72                 INT             data_len        -       the length of a specific data
73                 INT             len                     -       the output lenght
74
75         Return Value:
76                 UCHAR   *output         -       the calculated result
77
78         Note:
79                 802.11i-2004    Annex H.3
80
81         ========================================================================
82 */
83 VOID    PRF(
84         IN      UCHAR   *key,
85         IN      INT             key_len,
86         IN      UCHAR   *prefix,
87         IN      INT             prefix_len,
88         IN      UCHAR   *data,
89         IN      INT             data_len,
90         OUT     UCHAR   *output,
91         IN      INT             len)
92 {
93         INT             i;
94     UCHAR   *input;
95         INT             currentindex = 0;
96         INT             total_len;
97
98         // Allocate memory for input
99         os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
100
101     if (input == NULL)
102     {
103         DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
104         return;
105     }
106
107         // Generate concatenation input
108         NdisMoveMemory(input, prefix, prefix_len);
109
110         // Concatenate a single octet containing 0
111         input[prefix_len] =     0;
112
113         // Concatenate specific data
114         NdisMoveMemory(&input[prefix_len + 1], data, data_len);
115         total_len =     prefix_len + 1 + data_len;
116
117         // Concatenate a single octet containing 0
118         // This octet shall be update later
119         input[total_len] = 0;
120         total_len++;
121
122         // Iterate to calculate the result by hmac-sha-1
123         // Then concatenate to last result
124         for     (i = 0; i <     (len + 19) / 20; i++)
125         {
126                 HMAC_SHA1(input, total_len,     key, key_len, &output[currentindex]);
127                 currentindex += 20;
128
129                 // update the last octet
130                 input[total_len - 1]++;
131         }
132     os_free_mem(NULL, input);
133 }
134
135 /*
136         ========================================================================
137
138         Routine Description:
139                 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
140                 It shall be called by 4-way handshake processing.
141
142         Arguments:
143                 pAd     -       pointer to our pAdapter context
144                 PMK             -       pointer to PMK
145                 ANonce  -       pointer to ANonce
146                 AA              -       pointer to Authenticator Address
147                 SNonce  -       pointer to SNonce
148                 SA              -       pointer to Supplicant Address
149                 len             -       indicate the length of PTK (octet)
150
151         Return Value:
152                 Output          pointer to the PTK
153
154         Note:
155                 Refer to IEEE 802.11i-2004 8.5.1.2
156
157         ========================================================================
158 */
159 VOID WpaCountPTK(
160         IN      PRTMP_ADAPTER   pAd,
161         IN      UCHAR   *PMK,
162         IN      UCHAR   *ANonce,
163         IN      UCHAR   *AA,
164         IN      UCHAR   *SNonce,
165         IN      UCHAR   *SA,
166         OUT     UCHAR   *output,
167         IN      UINT    len)
168 {
169         UCHAR   concatenation[76];
170         UINT    CurrPos = 0;
171         UCHAR   temp[32];
172         UCHAR   Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
173                                                 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
174
175         // initiate the concatenation input
176         NdisZeroMemory(temp, sizeof(temp));
177         NdisZeroMemory(concatenation, 76);
178
179         // Get smaller address
180         if (RTMPCompareMemory(SA, AA, 6) == 1)
181                 NdisMoveMemory(concatenation, AA, 6);
182         else
183                 NdisMoveMemory(concatenation, SA, 6);
184         CurrPos += 6;
185
186         // Get larger address
187         if (RTMPCompareMemory(SA, AA, 6) == 1)
188                 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
189         else
190                 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
191
192         // store the larger mac address for backward compatible of
193         // ralink proprietary STA-key issue
194         NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
195         CurrPos += 6;
196
197         // Get smaller Nonce
198         if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
199                 NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
200         else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
201                 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
202         else
203                 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
204         CurrPos += 32;
205
206         // Get larger Nonce
207         if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
208                 NdisMoveMemory(&concatenation[CurrPos], temp, 32);      // patch for ralink proprietary STA-key issue
209         else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
210                 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
211         else
212                 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
213         CurrPos += 32;
214
215         hex_dump("concatenation=", concatenation, 76);
216
217         // Use PRF to generate PTK
218         PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
219
220 }
221
222 /*
223         ========================================================================
224
225         Routine Description:
226                 Generate random number by software.
227
228         Arguments:
229                 pAd             -       pointer to our pAdapter context
230                 macAddr -       pointer to local MAC address
231
232         Return Value:
233
234         Note:
235                 802.1ii-2004  Annex H.5
236
237         ========================================================================
238 */
239 VOID    GenRandom(
240         IN      PRTMP_ADAPTER   pAd,
241         IN      UCHAR                   *macAddr,
242         OUT     UCHAR                   *random)
243 {
244         INT             i, curr;
245         UCHAR   local[80], KeyCounter[32];
246         UCHAR   result[80];
247         ULONG   CurrentTime;
248         UCHAR   prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
249
250         // Zero the related information
251         NdisZeroMemory(result, 80);
252         NdisZeroMemory(local, 80);
253         NdisZeroMemory(KeyCounter, 32);
254
255         for     (i = 0; i <     32;     i++)
256         {
257                 // copy the local MAC address
258                 COPY_MAC_ADDR(local, macAddr);
259                 curr =  MAC_ADDR_LEN;
260
261                 // concatenate the current time
262                 NdisGetSystemUpTime(&CurrentTime);
263                 NdisMoveMemory(&local[curr],  &CurrentTime,     sizeof(CurrentTime));
264                 curr += sizeof(CurrentTime);
265
266                 // concatenate the last result
267                 NdisMoveMemory(&local[curr],  result, 32);
268                 curr += 32;
269
270                 // concatenate a variable
271                 NdisMoveMemory(&local[curr],  &i,  2);
272                 curr += 2;
273
274                 // calculate the result
275                 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
276         }
277
278         NdisMoveMemory(random, result,  32);
279 }
280
281 /*
282         ========================================================================
283
284         Routine Description:
285                 Build cipher suite in RSN-IE.
286                 It only shall be called by RTMPMakeRSNIE.
287
288         Arguments:
289                 pAd                     -       pointer to our pAdapter context
290         ElementID       -       indicate the WPA1 or WPA2
291         WepStatus       -       indicate the encryption type
292                 bMixCipher      -       a boolean to indicate the pairwise cipher and group
293                                                 cipher are the same or not
294
295         Return Value:
296
297         Note:
298
299         ========================================================================
300 */
301 static VOID RTMPInsertRsnIeCipher(
302         IN  PRTMP_ADAPTER   pAd,
303         IN      UCHAR                   ElementID,
304         IN      UINT                    WepStatus,
305         IN      BOOLEAN                 bMixCipher,
306         IN      UCHAR                   FlexibleCipher,
307         OUT     PUCHAR                  pRsnIe,
308         OUT     UCHAR                   *rsn_len)
309 {
310         UCHAR   PairwiseCnt;
311
312         *rsn_len = 0;
313
314         // decide WPA2 or WPA1
315         if (ElementID == Wpa2Ie)
316         {
317                 RSNIE2  *pRsnie_cipher = (RSNIE2*)pRsnIe;
318
319                 // Assign the verson as 1
320                 pRsnie_cipher->version = 1;
321
322         switch (WepStatus)
323         {
324                 // TKIP mode
325             case Ndis802_11Encryption2Enabled:
326                 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
327                 pRsnie_cipher->ucount = 1;
328                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
329                 *rsn_len = sizeof(RSNIE2);
330                 break;
331
332                         // AES mode
333             case Ndis802_11Encryption3Enabled:
334                                 if (bMixCipher)
335                                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
336                                 else
337                                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
338                 pRsnie_cipher->ucount = 1;
339                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
340                 *rsn_len = sizeof(RSNIE2);
341                 break;
342
343                         // TKIP-AES mix mode
344             case Ndis802_11Encryption4Enabled:
345                 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
346
347                                 PairwiseCnt = 1;
348                                 // Insert WPA2 TKIP as the first pairwise cipher
349                                 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
350                                 {
351                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
352                                         // Insert WPA2 AES as the secondary pairwise cipher
353                                         if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
354                                         {
355                                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
356                                                 PairwiseCnt = 2;
357                                         }
358                                 }
359                                 else
360                                 {
361                                         // Insert WPA2 AES as the first pairwise cipher
362                                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
363                                 }
364
365                 pRsnie_cipher->ucount = PairwiseCnt;
366                 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
367                 break;
368         }
369
370                 // swap for big-endian platform
371                 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
372             pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
373         }
374         else
375         {
376                 RSNIE   *pRsnie_cipher = (RSNIE*)pRsnIe;
377
378                 // Assign OUI and version
379                 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
380         pRsnie_cipher->version = 1;
381
382                 switch (WepStatus)
383                 {
384                         // TKIP mode
385             case Ndis802_11Encryption2Enabled:
386                 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
387                 pRsnie_cipher->ucount = 1;
388                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
389                 *rsn_len = sizeof(RSNIE);
390                 break;
391
392                         // AES mode
393             case Ndis802_11Encryption3Enabled:
394                                 if (bMixCipher)
395                                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
396                                 else
397                                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
398                 pRsnie_cipher->ucount = 1;
399                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
400                 *rsn_len = sizeof(RSNIE);
401                 break;
402
403                         // TKIP-AES mix mode
404             case Ndis802_11Encryption4Enabled:
405                 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
406
407                                 PairwiseCnt = 1;
408                                 // Insert WPA TKIP as the first pairwise cipher
409                                 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
410                                 {
411                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
412                                         // Insert WPA AES as the secondary pairwise cipher
413                                         if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
414                                         {
415                                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
416                                                 PairwiseCnt = 2;
417                                         }
418                                 }
419                                 else
420                                 {
421                                         // Insert WPA AES as the first pairwise cipher
422                                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
423                                 }
424
425                 pRsnie_cipher->ucount = PairwiseCnt;
426                 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
427                 break;
428         }
429
430                 // swap for big-endian platform
431                 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
432             pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
433         }
434
435 }
436
437 /*
438         ========================================================================
439
440         Routine Description:
441                 Build AKM suite in RSN-IE.
442                 It only shall be called by RTMPMakeRSNIE.
443
444         Arguments:
445                 pAd                     -       pointer to our pAdapter context
446         ElementID       -       indicate the WPA1 or WPA2
447         AuthMode        -       indicate the authentication mode
448                 apidx           -       indicate the interface index
449
450         Return Value:
451
452         Note:
453
454         ========================================================================
455 */
456 static VOID RTMPInsertRsnIeAKM(
457         IN  PRTMP_ADAPTER   pAd,
458         IN      UCHAR                   ElementID,
459         IN      UINT                    AuthMode,
460         IN      UCHAR                   apidx,
461         OUT     PUCHAR                  pRsnIe,
462         OUT     UCHAR                   *rsn_len)
463 {
464         RSNIE_AUTH              *pRsnie_auth;
465
466         pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
467
468         // decide WPA2 or WPA1
469         if (ElementID == Wpa2Ie)
470         {
471                 switch (AuthMode)
472         {
473             case Ndis802_11AuthModeWPA2:
474             case Ndis802_11AuthModeWPA1WPA2:
475                 pRsnie_auth->acount = 1;
476                         NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
477                 break;
478
479             case Ndis802_11AuthModeWPA2PSK:
480             case Ndis802_11AuthModeWPA1PSKWPA2PSK:
481                 pRsnie_auth->acount = 1;
482                         NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
483                 break;
484         }
485         }
486         else
487         {
488                 switch (AuthMode)
489         {
490             case Ndis802_11AuthModeWPA:
491             case Ndis802_11AuthModeWPA1WPA2:
492                 pRsnie_auth->acount = 1;
493                 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
494                 break;
495
496             case Ndis802_11AuthModeWPAPSK:
497             case Ndis802_11AuthModeWPA1PSKWPA2PSK:
498                 pRsnie_auth->acount = 1;
499                 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
500                 break;
501
502                         case Ndis802_11AuthModeWPANone:
503                 pRsnie_auth->acount = 1;
504                 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
505                 break;
506         }
507         }
508
509         pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
510
511         (*rsn_len) += sizeof(RSNIE_AUTH);       // update current RSNIE length
512
513 }
514
515 /*
516         ========================================================================
517
518         Routine Description:
519                 Build capability in RSN-IE.
520                 It only shall be called by RTMPMakeRSNIE.
521
522         Arguments:
523                 pAd                     -       pointer to our pAdapter context
524         ElementID       -       indicate the WPA1 or WPA2
525                 apidx           -       indicate the interface index
526
527         Return Value:
528
529         Note:
530
531         ========================================================================
532 */
533 static VOID RTMPInsertRsnIeCap(
534         IN  PRTMP_ADAPTER   pAd,
535         IN      UCHAR                   ElementID,
536         IN      UCHAR                   apidx,
537         OUT     PUCHAR                  pRsnIe,
538         OUT     UCHAR                   *rsn_len)
539 {
540         RSN_CAPABILITIES    *pRSN_Cap;
541
542         // it could be ignored in WPA1 mode
543         if (ElementID == WpaIe)
544                 return;
545
546         pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
547
548
549         pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
550
551         (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
552
553 }
554
555
556 /*
557         ========================================================================
558
559         Routine Description:
560                 Build RSN IE context. It is not included element-ID and length.
561
562         Arguments:
563                 pAd                     -       pointer to our pAdapter context
564         AuthMode        -       indicate the authentication mode
565         WepStatus       -       indicate the encryption type
566                 apidx           -       indicate the interface index
567
568         Return Value:
569
570         Note:
571
572         ========================================================================
573 */
574 VOID RTMPMakeRSNIE(
575     IN  PRTMP_ADAPTER   pAd,
576     IN  UINT            AuthMode,
577     IN  UINT            WepStatus,
578         IN      UCHAR                   apidx)
579 {
580         PUCHAR          pRsnIe = NULL;                  // primary RSNIE
581         UCHAR           *rsnielen_cur_p = 0;    // the length of the primary RSNIE
582         UCHAR           *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
583         UCHAR           PrimaryRsnie;
584         BOOLEAN         bMixCipher = FALSE;     // indicate the pairwise and group cipher are different
585         UCHAR           p_offset;
586         WPA_MIX_PAIR_CIPHER             FlexibleCipher = MIX_CIPHER_NOTUSE;     // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
587
588         rsnielen_cur_p = NULL;
589         rsnielen_ex_cur_p = NULL;
590
591         {
592 #ifdef CONFIG_STA_SUPPORT
593                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
594                 {
595 #ifdef WPA_SUPPLICANT_SUPPORT
596                         if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
597                         {
598                                 if (AuthMode < Ndis802_11AuthModeWPA)
599                                         return;
600                         }
601                         else
602 #endif // WPA_SUPPLICANT_SUPPORT //
603                         {
604                                 // Support WPAPSK or WPA2PSK in STA-Infra mode
605                                 // Support WPANone in STA-Adhoc mode
606                                 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
607                                         (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
608                                         (AuthMode != Ndis802_11AuthModeWPANone)
609                                         )
610                                         return;
611                         }
612
613                         DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
614
615                         // Zero RSNIE context
616                         pAd->StaCfg.RSNIE_Len = 0;
617                         NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
618
619                         // Pointer to RSNIE
620                         rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
621                         pRsnIe = pAd->StaCfg.RSN_IE;
622
623                         bMixCipher = pAd->StaCfg.bMixCipher;
624                 }
625 #endif // CONFIG_STA_SUPPORT //
626         }
627
628         // indicate primary RSNIE as WPA or WPA2
629         if ((AuthMode == Ndis802_11AuthModeWPA) ||
630                 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
631                 (AuthMode == Ndis802_11AuthModeWPANone) ||
632                 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
633                 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
634                 PrimaryRsnie = WpaIe;
635         else
636                 PrimaryRsnie = Wpa2Ie;
637
638         {
639                 // Build the primary RSNIE
640                 // 1. insert cipher suite
641                 RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
642
643                 // 2. insert AKM
644                 RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
645
646                 // 3. insert capability
647                 RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
648         }
649
650         // 4. update the RSNIE length
651         *rsnielen_cur_p = p_offset;
652
653         hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
654
655
656 }
657
658 /*
659     ==========================================================================
660     Description:
661                 Check whether the received frame is EAP frame.
662
663         Arguments:
664                 pAd                             -       pointer to our pAdapter context
665                 pEntry                  -       pointer to active entry
666                 pData                   -       the received frame
667                 DataByteCount   -       the received frame's length
668                 FromWhichBSSID  -       indicate the interface index
669
670     Return:
671          TRUE                   -       This frame is EAP frame
672          FALSE                  -       otherwise
673     ==========================================================================
674 */
675 BOOLEAN RTMPCheckWPAframe(
676     IN PRTMP_ADAPTER    pAd,
677     IN PMAC_TABLE_ENTRY pEntry,
678     IN PUCHAR           pData,
679     IN ULONG            DataByteCount,
680         IN UCHAR                        FromWhichBSSID)
681 {
682         ULONG   Body_len;
683         BOOLEAN Cancelled;
684
685
686     if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
687         return FALSE;
688
689
690         // Skip LLC header
691     if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
692         // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
693         NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
694     {
695         pData += 6;
696     }
697         // Skip 2-bytes EAPoL type
698     if (NdisEqualMemory(EAPOL, pData, 2))
699     {
700         pData += 2;
701     }
702     else
703         return FALSE;
704
705     switch (*(pData+1))
706     {
707         case EAPPacket:
708                         Body_len = (*(pData+2)<<8) | (*(pData+3));
709             DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
710             break;
711         case EAPOLStart:
712             DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
713                         if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
714             {
715                 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
716                 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
717                 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
718             }
719             break;
720         case EAPOLLogoff:
721             DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
722             break;
723         case EAPOLKey:
724                         Body_len = (*(pData+2)<<8) | (*(pData+3));
725             DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
726             break;
727         case EAPOLASFAlert:
728             DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
729             break;
730         default:
731             return FALSE;
732
733     }
734     return TRUE;
735 }
736
737
738 /*
739     ==========================================================================
740     Description:
741         ENCRYPT AES GTK before sending in EAPOL frame.
742         AES GTK length = 128 bit,  so fix blocks for aes-key-wrap as 2 in this function.
743         This function references to RFC 3394 for aes key wrap algorithm.
744     Return:
745     ==========================================================================
746 */
747 VOID AES_GTK_KEY_WRAP(
748     IN UCHAR    *key,
749     IN UCHAR    *plaintext,
750     IN UCHAR    p_len,
751     OUT UCHAR   *ciphertext)
752 {
753     UCHAR       A[8], BIN[16], BOUT[16];
754     UCHAR       R[512];
755     INT         num_blocks = p_len/8;   // unit:64bits
756     INT         i, j;
757     aes_context aesctx;
758     UCHAR       xor;
759
760     rtmp_aes_set_key(&aesctx, key, 128);
761
762     // Init IA
763     for (i = 0; i < 8; i++)
764         A[i] = 0xa6;
765
766     //Input plaintext
767     for (i = 0; i < num_blocks; i++)
768     {
769         for (j = 0 ; j < 8; j++)
770             R[8 * (i + 1) + j] = plaintext[8 * i + j];
771     }
772
773     // Key Mix
774     for (j = 0; j < 6; j++)
775     {
776         for(i = 1; i <= num_blocks; i++)
777         {
778             //phase 1
779             NdisMoveMemory(BIN, A, 8);
780             NdisMoveMemory(&BIN[8], &R[8 * i], 8);
781             rtmp_aes_encrypt(&aesctx, BIN, BOUT);
782
783             NdisMoveMemory(A, &BOUT[0], 8);
784             xor = num_blocks * j + i;
785             A[7] = BOUT[7] ^ xor;
786             NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
787         }
788     }
789
790     // Output ciphertext
791     NdisMoveMemory(ciphertext, A, 8);
792
793     for (i = 1; i <= num_blocks; i++)
794     {
795         for (j = 0 ; j < 8; j++)
796             ciphertext[8 * i + j] = R[8 * i + j];
797     }
798 }
799
800
801 /*
802         ========================================================================
803
804         Routine Description:
805                 Misc function to decrypt AES body
806
807         Arguments:
808
809         Return Value:
810
811         Note:
812                 This function references to     RFC     3394 for aes key unwrap algorithm.
813
814         ========================================================================
815 */
816 VOID    AES_GTK_KEY_UNWRAP(
817         IN      UCHAR   *key,
818         OUT     UCHAR   *plaintext,
819         IN      UCHAR    c_len,
820         IN      UCHAR   *ciphertext)
821
822 {
823         UCHAR       A[8], BIN[16], BOUT[16];
824         UCHAR       xor;
825         INT         i, j;
826         aes_context aesctx;
827         UCHAR       *R;
828         INT         num_blocks = c_len/8;       // unit:64bits
829
830
831         os_alloc_mem(NULL, (PUCHAR *)&R, 512);
832
833         if (R == NULL)
834     {
835         DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
836         return;
837     } /* End of if */
838
839         // Initialize
840         NdisMoveMemory(A, ciphertext, 8);
841         //Input plaintext
842         for(i = 0; i < (c_len-8); i++)
843         {
844                 R[ i] = ciphertext[i + 8];
845         }
846
847         rtmp_aes_set_key(&aesctx, key, 128);
848
849         for(j = 5; j >= 0; j--)
850         {
851                 for(i = (num_blocks-1); i > 0; i--)
852                 {
853                         xor = (num_blocks -1 )* j + i;
854                         NdisMoveMemory(BIN, A, 8);
855                         BIN[7] = A[7] ^ xor;
856                         NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
857                         rtmp_aes_decrypt(&aesctx, BIN, BOUT);
858                         NdisMoveMemory(A, &BOUT[0], 8);
859                         NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
860                 }
861         }
862
863         // OUTPUT
864         for(i = 0; i < c_len; i++)
865         {
866                 plaintext[i] = R[i];
867         }
868
869
870         os_free_mem(NULL, R);
871 }
872
873 /*
874     ==========================================================================
875     Description:
876                 Report the EAP message type
877
878         Arguments:
879                 msg             -       EAPOL_PAIR_MSG_1
880                                         EAPOL_PAIR_MSG_2
881                                         EAPOL_PAIR_MSG_3
882                                         EAPOL_PAIR_MSG_4
883                                         EAPOL_GROUP_MSG_1
884                                         EAPOL_GROUP_MSG_2
885
886     Return:
887          message type string
888
889     ==========================================================================
890 */
891 CHAR *GetEapolMsgType(CHAR msg)
892 {
893     if(msg == EAPOL_PAIR_MSG_1)
894         return "Pairwise Message 1";
895     else if(msg == EAPOL_PAIR_MSG_2)
896         return "Pairwise Message 2";
897         else if(msg == EAPOL_PAIR_MSG_3)
898         return "Pairwise Message 3";
899         else if(msg == EAPOL_PAIR_MSG_4)
900         return "Pairwise Message 4";
901         else if(msg == EAPOL_GROUP_MSG_1)
902         return "Group Message 1";
903         else if(msg == EAPOL_GROUP_MSG_2)
904         return "Group Message 2";
905     else
906         return "Invalid Message";
907 }
908
909
910 /*
911     ========================================================================
912
913     Routine Description:
914     Check Sanity RSN IE of EAPoL message
915
916     Arguments:
917
918     Return Value:
919
920
921     ========================================================================
922 */
923 BOOLEAN RTMPCheckRSNIE(
924         IN  PRTMP_ADAPTER   pAd,
925         IN  PUCHAR          pData,
926         IN  UCHAR           DataLen,
927         IN  MAC_TABLE_ENTRY *pEntry,
928         OUT     UCHAR                   *Offset)
929 {
930         PUCHAR              pVIE;
931         UCHAR               len;
932         PEID_STRUCT         pEid;
933         BOOLEAN                         result = FALSE;
934
935         pVIE = pData;
936         len      = DataLen;
937         *Offset = 0;
938
939         while (len > sizeof(RSNIE2))
940         {
941                 pEid = (PEID_STRUCT) pVIE;
942                 // WPA RSN IE
943                 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
944                 {
945                         if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
946                                 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
947                                 (pEntry->RSNIE_Len == (pEid->Len + 2)))
948                         {
949                                         result = TRUE;
950                         }
951
952                         *Offset += (pEid->Len + 2);
953                 }
954                 // WPA2 RSN IE
955                 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
956                 {
957                         if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
958                                 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
959                                 (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
960                         {
961                                         result = TRUE;
962                         }
963
964                         *Offset += (pEid->Len + 2);
965                 }
966                 else
967                 {
968                         break;
969                 }
970
971                 pVIE += (pEid->Len + 2);
972                 len  -= (pEid->Len + 2);
973         }
974
975
976         return result;
977
978 }
979
980
981 /*
982     ========================================================================
983
984     Routine Description:
985     Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
986     GTK  is encaptulated in KDE format at  p.83 802.11i D10
987
988     Arguments:
989
990     Return Value:
991
992     Note:
993         802.11i D10
994
995     ========================================================================
996 */
997 BOOLEAN RTMPParseEapolKeyData(
998         IN  PRTMP_ADAPTER   pAd,
999         IN  PUCHAR          pKeyData,
1000         IN  UCHAR           KeyDataLen,
1001         IN      UCHAR                   GroupKeyIndex,
1002         IN      UCHAR                   MsgType,
1003         IN      BOOLEAN                 bWPA2,
1004         IN  MAC_TABLE_ENTRY *pEntry)
1005 {
1006     PKDE_ENCAP          pKDE = NULL;
1007     PUCHAR              pMyKeyData = pKeyData;
1008     UCHAR               KeyDataLength = KeyDataLen;
1009     UCHAR               GTKLEN = 0;
1010         UCHAR                           DefaultIdx = 0;
1011         UCHAR                           skip_offset;
1012
1013         // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
1014         if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
1015     {
1016                 // Check RSN IE whether it is WPA2/WPA2PSK
1017                 if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
1018                 {
1019                         // send wireless event - for RSN IE different
1020                         if (pAd->CommonCfg.bWirelessEvent)
1021                                 RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1022
1023                 DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
1024                         hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
1025                         hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
1026
1027                         return FALSE;
1028         }
1029         else
1030                 {
1031                         if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
1032                         {
1033                                 // skip RSN IE
1034                                 pMyKeyData += skip_offset;
1035                                 KeyDataLength -= skip_offset;
1036                                 DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1037                         }
1038                         else
1039                                 return TRUE;
1040                 }
1041         }
1042
1043         DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1044
1045         // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
1046         if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
1047         {
1048                 if (KeyDataLength >= 8) // KDE format exclude GTK length
1049         {
1050                 pKDE = (PKDE_ENCAP) pMyKeyData;
1051
1052
1053                         DefaultIdx = pKDE->GTKEncap.Kid;
1054
1055                         // Sanity check - KED length
1056                         if (KeyDataLength < (pKDE->Len + 2))
1057                 {
1058                         DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1059                         return FALSE;
1060                 }
1061
1062                         // Get GTK length - refer to IEEE 802.11i-2004 p.82
1063                         GTKLEN = pKDE->Len -6;
1064                         if (GTKLEN < LEN_AES_KEY)
1065                         {
1066                                 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1067                         return FALSE;
1068                         }
1069
1070         }
1071                 else
1072         {
1073                         DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
1074                 return FALSE;
1075         }
1076
1077                 DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
1078                 // skip it
1079                 pMyKeyData += 8;
1080                 KeyDataLength -= 8;
1081
1082         }
1083         else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
1084         {
1085                 DefaultIdx = GroupKeyIndex;
1086                 DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
1087         }
1088
1089         // Sanity check - shared key index must be 1 ~ 3
1090         if (DefaultIdx < 1 || DefaultIdx > 3)
1091     {
1092         DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1093         return FALSE;
1094     }
1095
1096
1097 #ifdef CONFIG_STA_SUPPORT
1098         // Todo
1099 #endif // CONFIG_STA_SUPPORT //
1100
1101         return TRUE;
1102
1103 }
1104
1105
1106 /*
1107         ========================================================================
1108
1109         Routine Description:
1110                 Construct EAPoL message for WPA handshaking
1111                 Its format is below,
1112
1113                 +--------------------+
1114                 | Protocol Version       |  1 octet
1115                 +--------------------+
1116                 | Protocol Type          |      1 octet
1117                 +--------------------+
1118                 | Body Length            |  2 octets
1119                 +--------------------+
1120                 | Descriptor Type        |      1 octet
1121                 +--------------------+
1122                 | Key Information    |  2 octets
1123                 +--------------------+
1124                 | Key Length         |  1 octet
1125                 +--------------------+
1126                 | Key Repaly Counter |  8 octets
1127                 +--------------------+
1128                 | Key Nonce                  |  32 octets
1129                 +--------------------+
1130                 | Key IV                         |  16 octets
1131                 +--------------------+
1132                 | Key RSC                        |  8 octets
1133                 +--------------------+
1134                 | Key ID or Reserved |  8 octets
1135                 +--------------------+
1136                 | Key MIC                        |      16 octets
1137                 +--------------------+
1138                 | Key Data Length        |      2 octets
1139                 +--------------------+
1140                 | Key Data                       |      n octets
1141                 +--------------------+
1142
1143
1144         Arguments:
1145                 pAd                     Pointer to our adapter
1146
1147         Return Value:
1148                 None
1149
1150         Note:
1151
1152         ========================================================================
1153 */
1154 VOID    ConstructEapolMsg(
1155         IN      PRTMP_ADAPTER           pAd,
1156     IN  UCHAR                           AuthMode,
1157     IN  UCHAR                           WepStatus,
1158     IN  UCHAR                           GroupKeyWepStatus,
1159     IN  UCHAR                           MsgType,
1160     IN  UCHAR                           DefaultKeyIdx,
1161     IN  UCHAR                           *ReplayCounter,
1162         IN      UCHAR                           *KeyNonce,
1163         IN      UCHAR                           *TxRSC,
1164         IN      UCHAR                           *PTK,
1165         IN      UCHAR                           *GTK,
1166         IN      UCHAR                           *RSNIE,
1167         IN      UCHAR                           RSNIE_Len,
1168     OUT PEAPOL_PACKET       pMsg)
1169 {
1170         BOOLEAN bWPA2 = FALSE;
1171
1172         // Choose WPA2 or not
1173         if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
1174                 bWPA2 = TRUE;
1175
1176     // Init Packet and Fill header
1177     pMsg->ProVer = EAPOL_VER;
1178     pMsg->ProType = EAPOLKey;
1179
1180         // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
1181         pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
1182
1183         // Fill in EAPoL descriptor
1184         if (bWPA2)
1185                 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
1186         else
1187                 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
1188
1189         // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
1190         // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
1191         pMsg->KeyDesc.KeyInfo.KeyDescVer =
1192                 (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1193
1194         // Specify Key Type as Group(0) or Pairwise(1)
1195         if (MsgType >= EAPOL_GROUP_MSG_1)
1196                 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
1197         else
1198                 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1199
1200         // Specify Key Index, only group_msg1_WPA1
1201         if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
1202                 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
1203
1204         if (MsgType == EAPOL_PAIR_MSG_3)
1205                 pMsg->KeyDesc.KeyInfo.Install = 1;
1206
1207         if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
1208                 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
1209
1210         if (MsgType != EAPOL_PAIR_MSG_1)
1211                 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
1212
1213         if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
1214     {
1215         pMsg->KeyDesc.KeyInfo.Secure = 1;
1216     }
1217
1218         if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1219     {
1220         pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
1221     }
1222
1223         // key Information element has done.
1224         *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
1225
1226         // Fill in Key Length
1227         {
1228                 if (MsgType >= EAPOL_GROUP_MSG_1)
1229                 {
1230                         // the length of group key cipher
1231                         pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
1232                 }
1233                 else
1234                 {
1235                         // the length of pairwise key cipher
1236                         pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
1237                 }
1238         }
1239
1240         // Fill in replay counter
1241     NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
1242
1243         // Fill Key Nonce field
1244         // ANonce : pairwise_msg1 & pairwise_msg3
1245         // SNonce : pairwise_msg2
1246         // GNonce : group_msg1_wpa1
1247         if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
1248         NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
1249
1250         // Fill key IV - WPA2 as 0, WPA1 as random
1251         if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
1252         {
1253                 // Suggest IV be random number plus some number,
1254                 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
1255         pMsg->KeyDesc.KeyIv[15] += 2;
1256         }
1257
1258     // Fill Key RSC field
1259     // It contains the RSC for the GTK being installed.
1260         if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
1261         {
1262         NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
1263         }
1264
1265         // Clear Key MIC field for MIC calculation later
1266     NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1267
1268         ConstructEapolKeyData(pAd,
1269                                                   AuthMode,
1270                                                   WepStatus,
1271                                                   GroupKeyWepStatus,
1272                                                   MsgType,
1273                                                   DefaultKeyIdx,
1274                                                   bWPA2,
1275                                                   PTK,
1276                                                   GTK,
1277                                                   RSNIE,
1278                                                   RSNIE_Len,
1279                                                   pMsg);
1280
1281         // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
1282         if (MsgType != EAPOL_PAIR_MSG_1)
1283         {
1284                 CalculateMIC(pAd, WepStatus, PTK, pMsg);
1285         }
1286
1287         DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1288         DBGPRINT(RT_DEBUG_TRACE, ("          Body length = %d \n", pMsg->Body_Len[1]));
1289         DBGPRINT(RT_DEBUG_TRACE, ("          Key length  = %d \n", pMsg->KeyDesc.KeyLength[1]));
1290
1291
1292 }
1293
1294 /*
1295         ========================================================================
1296
1297         Routine Description:
1298                 Construct the Key Data field of EAPoL message
1299
1300         Arguments:
1301                 pAd                     Pointer to our adapter
1302                 Elem            Message body
1303
1304         Return Value:
1305                 None
1306
1307         Note:
1308
1309         ========================================================================
1310 */
1311 VOID    ConstructEapolKeyData(
1312         IN      PRTMP_ADAPTER   pAd,
1313         IN      UCHAR                   AuthMode,
1314         IN      UCHAR                   WepStatus,
1315         IN      UCHAR                   GroupKeyWepStatus,
1316         IN      UCHAR                   MsgType,
1317         IN      UCHAR                   DefaultKeyIdx,
1318         IN      BOOLEAN                 bWPA2Capable,
1319         IN      UCHAR                   *PTK,
1320         IN      UCHAR                   *GTK,
1321         IN      UCHAR                   *RSNIE,
1322         IN      UCHAR                   RSNIE_LEN,
1323         OUT PEAPOL_PACKET   pMsg)
1324 {
1325         UCHAR           *mpool, *Key_Data, *Rc4GTK;
1326         UCHAR       ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
1327         UCHAR           data_offset;
1328
1329
1330         if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
1331                 return;
1332
1333         // allocate memory pool
1334         os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
1335
1336     if (mpool == NULL)
1337                 return;
1338
1339         /* Rc4GTK Len = 512 */
1340         Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
1341         /* Key_Data Len = 512 */
1342         Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
1343
1344         NdisZeroMemory(Key_Data, 512);
1345         pMsg->KeyDesc.KeyDataLen[1] = 0;
1346         data_offset = 0;
1347
1348         // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
1349         if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
1350         {
1351                 if (bWPA2Capable)
1352                         Key_Data[data_offset + 0] = IE_WPA2;
1353                 else
1354                         Key_Data[data_offset + 0] = IE_WPA;
1355
1356         Key_Data[data_offset + 1] = RSNIE_LEN;
1357                 NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
1358                 data_offset += (2 + RSNIE_LEN);
1359         }
1360
1361         // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
1362         if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1363         {
1364                 // Key Data Encapsulation (KDE) format - 802.11i-2004  Figure-43w and Table-20h
1365         Key_Data[data_offset + 0] = 0xDD;
1366
1367                 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1368                 {
1369                         Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
1370                 }
1371                 else
1372                 {
1373                         Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
1374                 }
1375
1376         Key_Data[data_offset + 2] = 0x00;
1377         Key_Data[data_offset + 3] = 0x0F;
1378         Key_Data[data_offset + 4] = 0xAC;
1379         Key_Data[data_offset + 5] = 0x01;
1380
1381                 // GTK KDE format - 802.11i-2004  Figure-43x
1382         Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
1383         Key_Data[data_offset + 7] = 0x00;       // Reserved Byte
1384
1385                 data_offset += 8;
1386         }
1387
1388
1389         // Encapsulate GTK and encrypt the key-data field with KEK.
1390         // Only for pairwise_msg3_WPA2 and group_msg1
1391         if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
1392         {
1393                 // Fill in GTK
1394                 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1395                 {
1396                         NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
1397                         data_offset += LEN_AES_KEY;
1398                 }
1399                 else
1400                 {
1401                         NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
1402                         data_offset += TKIP_GTK_LENGTH;
1403                 }
1404
1405                 // Still dont know why, but if not append will occur "GTK not include in MSG3"
1406                 // Patch for compatibility between zero config and funk
1407                 if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
1408                 {
1409                         if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1410                         {
1411                                 Key_Data[data_offset + 0] = 0xDD;
1412                                 Key_Data[data_offset + 1] = 0;
1413                                 data_offset += 2;
1414                         }
1415                         else
1416                         {
1417                                 Key_Data[data_offset + 0] = 0xDD;
1418                                 Key_Data[data_offset + 1] = 0;
1419                                 Key_Data[data_offset + 2] = 0;
1420                                 Key_Data[data_offset + 3] = 0;
1421                                 Key_Data[data_offset + 4] = 0;
1422                                 Key_Data[data_offset + 5] = 0;
1423                                 data_offset += 6;
1424                         }
1425                 }
1426
1427                 // Encrypt the data material in key data field
1428                 if (WepStatus == Ndis802_11Encryption3Enabled)
1429                 {
1430                         AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
1431             // AES wrap function will grow 8 bytes in length
1432             data_offset += 8;
1433                 }
1434                 else
1435                 {
1436                         // PREPARE Encrypted  "Key DATA" field.  (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
1437                         // put TxTsc in Key RSC field
1438                         pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32;   //Init crc32.
1439
1440                         // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
1441                         NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
1442                         NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
1443                         ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey));  //INIT SBOX, KEYLEN+3(IV)
1444                         pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
1445                         WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
1446                 }
1447
1448                 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
1449         }
1450         else
1451         {
1452                 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
1453         }
1454
1455         // set key data length field and total length
1456         pMsg->KeyDesc.KeyDataLen[1] = data_offset;
1457     pMsg->Body_Len[1] += data_offset;
1458
1459         os_free_mem(pAd, mpool);
1460
1461 }
1462
1463 /*
1464         ========================================================================
1465
1466         Routine Description:
1467                 Calcaulate MIC. It is used during 4-ways handsharking.
1468
1469         Arguments:
1470                 pAd                             -       pointer to our pAdapter context
1471         PeerWepStatus   -       indicate the encryption type
1472
1473         Return Value:
1474
1475         Note:
1476
1477         ========================================================================
1478 */
1479 VOID    CalculateMIC(
1480         IN      PRTMP_ADAPTER   pAd,
1481         IN      UCHAR                   PeerWepStatus,
1482         IN      UCHAR                   *PTK,
1483         OUT PEAPOL_PACKET   pMsg)
1484 {
1485     UCHAR   *OutBuffer;
1486         ULONG   FrameLen = 0;
1487         UCHAR   mic[LEN_KEY_DESC_MIC];
1488         UCHAR   digest[80];
1489
1490         // allocate memory for MIC calculation
1491         os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
1492
1493     if (OutBuffer == NULL)
1494     {
1495                 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
1496                 return;
1497     }
1498
1499         // make a frame for calculating MIC.
1500     MakeOutgoingFrame(OutBuffer,                &FrameLen,
1501                       pMsg->Body_Len[1] + 4,    pMsg,
1502                       END_OF_ARGS);
1503
1504         NdisZeroMemory(mic, sizeof(mic));
1505
1506         // Calculate MIC
1507     if (PeerWepStatus == Ndis802_11Encryption3Enabled)
1508         {
1509                 HMAC_SHA1(OutBuffer,  FrameLen, PTK, LEN_EAP_MICK, digest);
1510                 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
1511         }
1512         else
1513         {
1514                 hmac_md5(PTK,  LEN_EAP_MICK, OutBuffer, FrameLen, mic);
1515         }
1516
1517         // store the calculated MIC
1518         NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
1519
1520         os_free_mem(pAd, OutBuffer);
1521 }
1522
1523 /*
1524         ========================================================================
1525
1526         Routine Description:
1527                 Some received frames can't decrypt by Asic, so decrypt them by software.
1528
1529         Arguments:
1530                 pAd                             -       pointer to our pAdapter context
1531         PeerWepStatus   -       indicate the encryption type
1532
1533         Return Value:
1534                 NDIS_STATUS_SUCCESS             -       decryption successful
1535                 NDIS_STATUS_FAILURE             -       decryption failure
1536
1537         ========================================================================
1538 */
1539 NDIS_STATUS     RTMPSoftDecryptBroadCastData(
1540         IN      PRTMP_ADAPTER                                   pAd,
1541         IN      RX_BLK                                                  *pRxBlk,
1542         IN  NDIS_802_11_ENCRYPTION_STATUS       GroupCipher,
1543         IN  PCIPHER_KEY                                         pShard_key)
1544 {
1545         PRXWI_STRUC                     pRxWI = pRxBlk->pRxWI;
1546
1547
1548
1549         // handle WEP decryption
1550         if (GroupCipher == Ndis802_11Encryption1Enabled)
1551     {
1552                 if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
1553                 {
1554
1555                         //Minus IV[4] & ICV[4]
1556                         pRxWI->MPDUtotalByteCount -= 8;
1557                 }
1558                 else
1559                 {
1560                         DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
1561                         // give up this frame
1562                         return NDIS_STATUS_FAILURE;
1563                 }
1564         }
1565         // handle TKIP decryption
1566         else if (GroupCipher == Ndis802_11Encryption2Enabled)
1567         {
1568                 if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
1569                 {
1570
1571                         //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
1572                         pRxWI->MPDUtotalByteCount -= 20;
1573                 }
1574         else
1575                 {
1576                         DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
1577                         // give up this frame
1578                         return NDIS_STATUS_FAILURE;
1579         }
1580         }
1581         // handle AES decryption
1582         else if (GroupCipher == Ndis802_11Encryption3Enabled)
1583         {
1584                 if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
1585                 {
1586
1587                         //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
1588                         pRxWI->MPDUtotalByteCount -= 16;
1589                 }
1590                 else
1591                 {
1592                         DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
1593                         // give up this frame
1594                         return NDIS_STATUS_FAILURE;
1595                 }
1596         }
1597         else
1598         {
1599                 // give up this frame
1600                 return NDIS_STATUS_FAILURE;
1601         }
1602
1603         return NDIS_STATUS_SUCCESS;
1604
1605 }
1606