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