Merge commit 'v2.6.30-rc1' into core/urgent
[linux-2.6] / drivers / staging / rt2860 / 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_WEP40[4]      = {0x00, 0x50, 0xF2, 0x01};
43 UCHAR       OUI_WPA_TKIP[4]     = {0x00, 0x50, 0xF2, 0x02};
44 UCHAR       OUI_WPA_CCMP[4]     = {0x00, 0x50, 0xF2, 0x04};
45 UCHAR       OUI_WPA_WEP104[4]      = {0x00, 0x50, 0xF2, 0x05};
46 UCHAR       OUI_WPA_8021X_AKM[4]        = {0x00, 0x50, 0xF2, 0x01};
47 UCHAR       OUI_WPA_PSK_AKM[4]      = {0x00, 0x50, 0xF2, 0x02};
48 // WPA2 OUI
49 UCHAR       OUI_WPA2_WEP40[4]   = {0x00, 0x0F, 0xAC, 0x01};
50 UCHAR       OUI_WPA2_TKIP[4]        = {0x00, 0x0F, 0xAC, 0x02};
51 UCHAR       OUI_WPA2_CCMP[4]        = {0x00, 0x0F, 0xAC, 0x04};
52 UCHAR       OUI_WPA2_8021X_AKM[4]   = {0x00, 0x0F, 0xAC, 0x01};
53 UCHAR       OUI_WPA2_PSK_AKM[4]         = {0x00, 0x0F, 0xAC, 0x02};
54 UCHAR       OUI_WPA2_WEP104[4]   = {0x00, 0x0F, 0xAC, 0x05};
55 // MSA OUI
56 UCHAR           OUI_MSA_8021X_AKM[4]    = {0x00, 0x0F, 0xAC, 0x05};             // Not yet final - IEEE 802.11s-D1.06
57 UCHAR           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 */
86 VOID    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 */
162 VOID 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 */
242 VOID    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 */
304 static 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 */
494 static 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 */
571 static 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 */
612 VOID 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 */
713 BOOLEAN 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 */
785 VOID 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 */
854 VOID    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 */
929 CHAR *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 */
961 BOOLEAN 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 */
1035 BOOLEAN 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 */
1192 VOID    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 */
1349 VOID    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 */
1517 VOID    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 */
1577 NDIS_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