added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / staging / rt2860 / common / cmm_wpa.c
blob81c332ac25244da5cc5bad48d58533c119bb2a3b
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
27 Module Name:
28 wpa.c
30 Abstract:
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
38 #include "../rt_config.h"
39 // WPA OUI
40 UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00};
41 UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01};
42 UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
43 UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
44 UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
45 UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
46 // WPA2 OUI
47 UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
48 UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
49 UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
50 UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
51 UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
52 // MSA OUI
53 UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06
54 UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06
57 ========================================================================
59 Routine Description:
60 The pseudo-random function(PRF) that hashes various inputs to
61 derive a pseudo-random value. To add liveness to the pseudo-random
62 value, a nonce should be one of the inputs.
64 It is used to generate PTK, GTK or some specific random value.
66 Arguments:
67 UCHAR *key, - the key material for HMAC_SHA1 use
68 INT key_len - the length of key
69 UCHAR *prefix - a prefix label
70 INT prefix_len - the length of the label
71 UCHAR *data - a specific data with variable length
72 INT data_len - the length of a specific data
73 INT len - the output lenght
75 Return Value:
76 UCHAR *output - the calculated result
78 Note:
79 802.11i-2004 Annex H.3
81 ========================================================================
83 VOID PRF(
84 IN UCHAR *key,
85 IN INT key_len,
86 IN UCHAR *prefix,
87 IN INT prefix_len,
88 IN UCHAR *data,
89 IN INT data_len,
90 OUT UCHAR *output,
91 IN INT len)
93 INT i;
94 UCHAR *input;
95 INT currentindex = 0;
96 INT total_len;
98 // Allocate memory for input
99 os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
101 if (input == NULL)
103 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
104 return;
107 // Generate concatenation input
108 NdisMoveMemory(input, prefix, prefix_len);
110 // Concatenate a single octet containing 0
111 input[prefix_len] = 0;
113 // Concatenate specific data
114 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
115 total_len = prefix_len + 1 + data_len;
117 // Concatenate a single octet containing 0
118 // This octet shall be update later
119 input[total_len] = 0;
120 total_len++;
122 // Iterate to calculate the result by hmac-sha-1
123 // Then concatenate to last result
124 for (i = 0; i < (len + 19) / 20; i++)
126 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
127 currentindex += 20;
129 // update the last octet
130 input[total_len - 1]++;
132 os_free_mem(NULL, input);
136 ========================================================================
138 Routine Description:
139 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
140 It shall be called by 4-way handshake processing.
142 Arguments:
143 pAd - pointer to our pAdapter context
144 PMK - pointer to PMK
145 ANonce - pointer to ANonce
146 AA - pointer to Authenticator Address
147 SNonce - pointer to SNonce
148 SA - pointer to Supplicant Address
149 len - indicate the length of PTK (octet)
151 Return Value:
152 Output pointer to the PTK
154 Note:
155 Refer to IEEE 802.11i-2004 8.5.1.2
157 ========================================================================
159 VOID WpaCountPTK(
160 IN PRTMP_ADAPTER pAd,
161 IN UCHAR *PMK,
162 IN UCHAR *ANonce,
163 IN UCHAR *AA,
164 IN UCHAR *SNonce,
165 IN UCHAR *SA,
166 OUT UCHAR *output,
167 IN UINT len)
169 UCHAR concatenation[76];
170 UINT CurrPos = 0;
171 UCHAR temp[32];
172 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
173 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
175 // initiate the concatenation input
176 NdisZeroMemory(temp, sizeof(temp));
177 NdisZeroMemory(concatenation, 76);
179 // Get smaller address
180 if (RTMPCompareMemory(SA, AA, 6) == 1)
181 NdisMoveMemory(concatenation, AA, 6);
182 else
183 NdisMoveMemory(concatenation, SA, 6);
184 CurrPos += 6;
186 // Get larger address
187 if (RTMPCompareMemory(SA, AA, 6) == 1)
188 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
189 else
190 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
192 // store the larger mac address for backward compatible of
193 // ralink proprietary STA-key issue
194 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
195 CurrPos += 6;
197 // Get smaller Nonce
198 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
199 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
200 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
201 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
202 else
203 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
204 CurrPos += 32;
206 // Get larger Nonce
207 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
208 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
209 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
210 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
211 else
212 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
213 CurrPos += 32;
215 hex_dump("concatenation=", concatenation, 76);
217 // Use PRF to generate PTK
218 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
223 ========================================================================
225 Routine Description:
226 Generate random number by software.
228 Arguments:
229 pAd - pointer to our pAdapter context
230 macAddr - pointer to local MAC address
232 Return Value:
234 Note:
235 802.1ii-2004 Annex H.5
237 ========================================================================
239 VOID GenRandom(
240 IN PRTMP_ADAPTER pAd,
241 IN UCHAR *macAddr,
242 OUT UCHAR *random)
244 INT i, curr;
245 UCHAR local[80], KeyCounter[32];
246 UCHAR result[80];
247 ULONG CurrentTime;
248 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
250 // Zero the related information
251 NdisZeroMemory(result, 80);
252 NdisZeroMemory(local, 80);
253 NdisZeroMemory(KeyCounter, 32);
255 for (i = 0; i < 32; i++)
257 // copy the local MAC address
258 COPY_MAC_ADDR(local, macAddr);
259 curr = MAC_ADDR_LEN;
261 // concatenate the current time
262 NdisGetSystemUpTime(&CurrentTime);
263 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
264 curr += sizeof(CurrentTime);
266 // concatenate the last result
267 NdisMoveMemory(&local[curr], result, 32);
268 curr += 32;
270 // concatenate a variable
271 NdisMoveMemory(&local[curr], &i, 2);
272 curr += 2;
274 // calculate the result
275 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
278 NdisMoveMemory(random, result, 32);
282 ========================================================================
284 Routine Description:
285 Build cipher suite in RSN-IE.
286 It only shall be called by RTMPMakeRSNIE.
288 Arguments:
289 pAd - pointer to our pAdapter context
290 ElementID - indicate the WPA1 or WPA2
291 WepStatus - indicate the encryption type
292 bMixCipher - a boolean to indicate the pairwise cipher and group
293 cipher are the same or not
295 Return Value:
297 Note:
299 ========================================================================
301 static VOID RTMPInsertRsnIeCipher(
302 IN PRTMP_ADAPTER pAd,
303 IN UCHAR ElementID,
304 IN UINT WepStatus,
305 IN BOOLEAN bMixCipher,
306 IN UCHAR FlexibleCipher,
307 OUT PUCHAR pRsnIe,
308 OUT UCHAR *rsn_len)
310 UCHAR PairwiseCnt;
312 *rsn_len = 0;
314 // decide WPA2 or WPA1
315 if (ElementID == Wpa2Ie)
317 RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
319 // Assign the verson as 1
320 pRsnie_cipher->version = 1;
322 switch (WepStatus)
324 // TKIP mode
325 case Ndis802_11Encryption2Enabled:
326 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
327 pRsnie_cipher->ucount = 1;
328 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
329 *rsn_len = sizeof(RSNIE2);
330 break;
332 // AES mode
333 case Ndis802_11Encryption3Enabled:
334 if (bMixCipher)
335 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
336 else
337 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
338 pRsnie_cipher->ucount = 1;
339 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
340 *rsn_len = sizeof(RSNIE2);
341 break;
343 // TKIP-AES mix mode
344 case Ndis802_11Encryption4Enabled:
345 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
347 PairwiseCnt = 1;
348 // Insert WPA2 TKIP as the first pairwise cipher
349 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
351 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
352 // Insert WPA2 AES as the secondary pairwise cipher
353 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
355 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
356 PairwiseCnt = 2;
359 else
361 // Insert WPA2 AES as the first pairwise cipher
362 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
365 pRsnie_cipher->ucount = PairwiseCnt;
366 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
367 break;
370 // swap for big-endian platform
371 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
372 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
374 else
376 RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
378 // Assign OUI and version
379 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
380 pRsnie_cipher->version = 1;
382 switch (WepStatus)
384 // TKIP mode
385 case Ndis802_11Encryption2Enabled:
386 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
387 pRsnie_cipher->ucount = 1;
388 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
389 *rsn_len = sizeof(RSNIE);
390 break;
392 // AES mode
393 case Ndis802_11Encryption3Enabled:
394 if (bMixCipher)
395 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
396 else
397 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
398 pRsnie_cipher->ucount = 1;
399 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
400 *rsn_len = sizeof(RSNIE);
401 break;
403 // TKIP-AES mix mode
404 case Ndis802_11Encryption4Enabled:
405 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
407 PairwiseCnt = 1;
408 // Insert WPA TKIP as the first pairwise cipher
409 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
411 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
412 // Insert WPA AES as the secondary pairwise cipher
413 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
415 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
416 PairwiseCnt = 2;
419 else
421 // Insert WPA AES as the first pairwise cipher
422 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
425 pRsnie_cipher->ucount = PairwiseCnt;
426 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
427 break;
430 // swap for big-endian platform
431 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
432 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
438 ========================================================================
440 Routine Description:
441 Build AKM suite in RSN-IE.
442 It only shall be called by RTMPMakeRSNIE.
444 Arguments:
445 pAd - pointer to our pAdapter context
446 ElementID - indicate the WPA1 or WPA2
447 AuthMode - indicate the authentication mode
448 apidx - indicate the interface index
450 Return Value:
452 Note:
454 ========================================================================
456 static VOID RTMPInsertRsnIeAKM(
457 IN PRTMP_ADAPTER pAd,
458 IN UCHAR ElementID,
459 IN UINT AuthMode,
460 IN UCHAR apidx,
461 OUT PUCHAR pRsnIe,
462 OUT UCHAR *rsn_len)
464 RSNIE_AUTH *pRsnie_auth;
466 pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
468 // decide WPA2 or WPA1
469 if (ElementID == Wpa2Ie)
471 switch (AuthMode)
473 case Ndis802_11AuthModeWPA2:
474 case Ndis802_11AuthModeWPA1WPA2:
475 pRsnie_auth->acount = 1;
476 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
477 break;
479 case Ndis802_11AuthModeWPA2PSK:
480 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
481 pRsnie_auth->acount = 1;
482 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
483 break;
486 else
488 switch (AuthMode)
490 case Ndis802_11AuthModeWPA:
491 case Ndis802_11AuthModeWPA1WPA2:
492 pRsnie_auth->acount = 1;
493 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
494 break;
496 case Ndis802_11AuthModeWPAPSK:
497 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
498 pRsnie_auth->acount = 1;
499 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
500 break;
502 case Ndis802_11AuthModeWPANone:
503 pRsnie_auth->acount = 1;
504 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
505 break;
509 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
511 (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length
516 ========================================================================
518 Routine Description:
519 Build capability in RSN-IE.
520 It only shall be called by RTMPMakeRSNIE.
522 Arguments:
523 pAd - pointer to our pAdapter context
524 ElementID - indicate the WPA1 or WPA2
525 apidx - indicate the interface index
527 Return Value:
529 Note:
531 ========================================================================
533 static VOID RTMPInsertRsnIeCap(
534 IN PRTMP_ADAPTER pAd,
535 IN UCHAR ElementID,
536 IN UCHAR apidx,
537 OUT PUCHAR pRsnIe,
538 OUT UCHAR *rsn_len)
540 RSN_CAPABILITIES *pRSN_Cap;
542 // it could be ignored in WPA1 mode
543 if (ElementID == WpaIe)
544 return;
546 pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
549 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
551 (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
557 ========================================================================
559 Routine Description:
560 Build RSN IE context. It is not included element-ID and length.
562 Arguments:
563 pAd - pointer to our pAdapter context
564 AuthMode - indicate the authentication mode
565 WepStatus - indicate the encryption type
566 apidx - indicate the interface index
568 Return Value:
570 Note:
572 ========================================================================
574 VOID RTMPMakeRSNIE(
575 IN PRTMP_ADAPTER pAd,
576 IN UINT AuthMode,
577 IN UINT WepStatus,
578 IN UCHAR apidx)
580 PUCHAR pRsnIe = NULL; // primary RSNIE
581 UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE
582 UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
583 UCHAR PrimaryRsnie;
584 BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
585 UCHAR p_offset;
586 WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
588 rsnielen_cur_p = NULL;
589 rsnielen_ex_cur_p = NULL;
592 #ifdef CONFIG_STA_SUPPORT
593 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
595 #ifdef WPA_SUPPLICANT_SUPPORT
596 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
598 if (AuthMode < Ndis802_11AuthModeWPA)
599 return;
601 else
602 #endif // WPA_SUPPLICANT_SUPPORT //
604 // Support WPAPSK or WPA2PSK in STA-Infra mode
605 // Support WPANone in STA-Adhoc mode
606 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
607 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
608 (AuthMode != Ndis802_11AuthModeWPANone)
610 return;
613 DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
615 // Zero RSNIE context
616 pAd->StaCfg.RSNIE_Len = 0;
617 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
619 // Pointer to RSNIE
620 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
621 pRsnIe = pAd->StaCfg.RSN_IE;
623 bMixCipher = pAd->StaCfg.bMixCipher;
625 #endif // CONFIG_STA_SUPPORT //
628 // indicate primary RSNIE as WPA or WPA2
629 if ((AuthMode == Ndis802_11AuthModeWPA) ||
630 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
631 (AuthMode == Ndis802_11AuthModeWPANone) ||
632 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
633 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
634 PrimaryRsnie = WpaIe;
635 else
636 PrimaryRsnie = Wpa2Ie;
639 // Build the primary RSNIE
640 // 1. insert cipher suite
641 RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
643 // 2. insert AKM
644 RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
646 // 3. insert capability
647 RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
650 // 4. update the RSNIE length
651 *rsnielen_cur_p = p_offset;
653 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
659 ==========================================================================
660 Description:
661 Check whether the received frame is EAP frame.
663 Arguments:
664 pAd - pointer to our pAdapter context
665 pEntry - pointer to active entry
666 pData - the received frame
667 DataByteCount - the received frame's length
668 FromWhichBSSID - indicate the interface index
670 Return:
671 TRUE - This frame is EAP frame
672 FALSE - otherwise
673 ==========================================================================
675 BOOLEAN RTMPCheckWPAframe(
676 IN PRTMP_ADAPTER pAd,
677 IN PMAC_TABLE_ENTRY pEntry,
678 IN PUCHAR pData,
679 IN ULONG DataByteCount,
680 IN UCHAR FromWhichBSSID)
682 ULONG Body_len;
683 BOOLEAN Cancelled;
686 if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
687 return FALSE;
690 // Skip LLC header
691 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
692 // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
693 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
695 pData += 6;
697 // Skip 2-bytes EAPoL type
698 if (NdisEqualMemory(EAPOL, pData, 2))
700 pData += 2;
702 else
703 return FALSE;
705 switch (*(pData+1))
707 case EAPPacket:
708 Body_len = (*(pData+2)<<8) | (*(pData+3));
709 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
710 break;
711 case EAPOLStart:
712 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
713 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
715 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
716 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
717 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
719 break;
720 case EAPOLLogoff:
721 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
722 break;
723 case EAPOLKey:
724 Body_len = (*(pData+2)<<8) | (*(pData+3));
725 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
726 break;
727 case EAPOLASFAlert:
728 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
729 break;
730 default:
731 return FALSE;
734 return TRUE;
739 ==========================================================================
740 Description:
741 ENCRYPT AES GTK before sending in EAPOL frame.
742 AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function.
743 This function references to RFC 3394 for aes key wrap algorithm.
744 Return:
745 ==========================================================================
747 VOID AES_GTK_KEY_WRAP(
748 IN UCHAR *key,
749 IN UCHAR *plaintext,
750 IN UCHAR p_len,
751 OUT UCHAR *ciphertext)
753 UCHAR A[8], BIN[16], BOUT[16];
754 UCHAR R[512];
755 INT num_blocks = p_len/8; // unit:64bits
756 INT i, j;
757 aes_context aesctx;
758 UCHAR xor;
760 rtmp_aes_set_key(&aesctx, key, 128);
762 // Init IA
763 for (i = 0; i < 8; i++)
764 A[i] = 0xa6;
766 //Input plaintext
767 for (i = 0; i < num_blocks; i++)
769 for (j = 0 ; j < 8; j++)
770 R[8 * (i + 1) + j] = plaintext[8 * i + j];
773 // Key Mix
774 for (j = 0; j < 6; j++)
776 for(i = 1; i <= num_blocks; i++)
778 //phase 1
779 NdisMoveMemory(BIN, A, 8);
780 NdisMoveMemory(&BIN[8], &R[8 * i], 8);
781 rtmp_aes_encrypt(&aesctx, BIN, BOUT);
783 NdisMoveMemory(A, &BOUT[0], 8);
784 xor = num_blocks * j + i;
785 A[7] = BOUT[7] ^ xor;
786 NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
790 // Output ciphertext
791 NdisMoveMemory(ciphertext, A, 8);
793 for (i = 1; i <= num_blocks; i++)
795 for (j = 0 ; j < 8; j++)
796 ciphertext[8 * i + j] = R[8 * i + j];
802 ========================================================================
804 Routine Description:
805 Misc function to decrypt AES body
807 Arguments:
809 Return Value:
811 Note:
812 This function references to RFC 3394 for aes key unwrap algorithm.
814 ========================================================================
816 VOID AES_GTK_KEY_UNWRAP(
817 IN UCHAR *key,
818 OUT UCHAR *plaintext,
819 IN UCHAR c_len,
820 IN UCHAR *ciphertext)
823 UCHAR A[8], BIN[16], BOUT[16];
824 UCHAR xor;
825 INT i, j;
826 aes_context aesctx;
827 UCHAR *R;
828 INT num_blocks = c_len/8; // unit:64bits
831 os_alloc_mem(NULL, (PUCHAR *)&R, 512);
833 if (R == NULL)
835 DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
836 return;
837 } /* End of if */
839 // Initialize
840 NdisMoveMemory(A, ciphertext, 8);
841 //Input plaintext
842 for(i = 0; i < (c_len-8); i++)
844 R[ i] = ciphertext[i + 8];
847 rtmp_aes_set_key(&aesctx, key, 128);
849 for(j = 5; j >= 0; j--)
851 for(i = (num_blocks-1); i > 0; i--)
853 xor = (num_blocks -1 )* j + i;
854 NdisMoveMemory(BIN, A, 8);
855 BIN[7] = A[7] ^ xor;
856 NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
857 rtmp_aes_decrypt(&aesctx, BIN, BOUT);
858 NdisMoveMemory(A, &BOUT[0], 8);
859 NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
863 // OUTPUT
864 for(i = 0; i < c_len; i++)
866 plaintext[i] = R[i];
870 os_free_mem(NULL, R);
874 ==========================================================================
875 Description:
876 Report the EAP message type
878 Arguments:
879 msg - EAPOL_PAIR_MSG_1
880 EAPOL_PAIR_MSG_2
881 EAPOL_PAIR_MSG_3
882 EAPOL_PAIR_MSG_4
883 EAPOL_GROUP_MSG_1
884 EAPOL_GROUP_MSG_2
886 Return:
887 message type string
889 ==========================================================================
891 CHAR *GetEapolMsgType(CHAR msg)
893 if(msg == EAPOL_PAIR_MSG_1)
894 return "Pairwise Message 1";
895 else if(msg == EAPOL_PAIR_MSG_2)
896 return "Pairwise Message 2";
897 else if(msg == EAPOL_PAIR_MSG_3)
898 return "Pairwise Message 3";
899 else if(msg == EAPOL_PAIR_MSG_4)
900 return "Pairwise Message 4";
901 else if(msg == EAPOL_GROUP_MSG_1)
902 return "Group Message 1";
903 else if(msg == EAPOL_GROUP_MSG_2)
904 return "Group Message 2";
905 else
906 return "Invalid Message";
911 ========================================================================
913 Routine Description:
914 Check Sanity RSN IE of EAPoL message
916 Arguments:
918 Return Value:
921 ========================================================================
923 BOOLEAN RTMPCheckRSNIE(
924 IN PRTMP_ADAPTER pAd,
925 IN PUCHAR pData,
926 IN UCHAR DataLen,
927 IN MAC_TABLE_ENTRY *pEntry,
928 OUT UCHAR *Offset)
930 PUCHAR pVIE;
931 UCHAR len;
932 PEID_STRUCT pEid;
933 BOOLEAN result = FALSE;
935 pVIE = pData;
936 len = DataLen;
937 *Offset = 0;
939 while (len > sizeof(RSNIE2))
941 pEid = (PEID_STRUCT) pVIE;
942 // WPA RSN IE
943 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
945 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
946 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
947 (pEntry->RSNIE_Len == (pEid->Len + 2)))
949 result = TRUE;
952 *Offset += (pEid->Len + 2);
954 // WPA2 RSN IE
955 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
957 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
958 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
959 (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
961 result = TRUE;
964 *Offset += (pEid->Len + 2);
966 else
968 break;
971 pVIE += (pEid->Len + 2);
972 len -= (pEid->Len + 2);
976 return result;
982 ========================================================================
984 Routine Description:
985 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
986 GTK is encaptulated in KDE format at p.83 802.11i D10
988 Arguments:
990 Return Value:
992 Note:
993 802.11i D10
995 ========================================================================
997 BOOLEAN RTMPParseEapolKeyData(
998 IN PRTMP_ADAPTER pAd,
999 IN PUCHAR pKeyData,
1000 IN UCHAR KeyDataLen,
1001 IN UCHAR GroupKeyIndex,
1002 IN UCHAR MsgType,
1003 IN BOOLEAN bWPA2,
1004 IN MAC_TABLE_ENTRY *pEntry)
1006 PKDE_ENCAP pKDE = NULL;
1007 PUCHAR pMyKeyData = pKeyData;
1008 UCHAR KeyDataLength = KeyDataLen;
1009 UCHAR GTKLEN = 0;
1010 UCHAR DefaultIdx = 0;
1011 UCHAR skip_offset;
1013 // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
1014 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
1016 // Check RSN IE whether it is WPA2/WPA2PSK
1017 if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
1019 // send wireless event - for RSN IE different
1020 if (pAd->CommonCfg.bWirelessEvent)
1021 RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1023 DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
1024 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
1025 hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
1027 return FALSE;
1029 else
1031 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
1033 // skip RSN IE
1034 pMyKeyData += skip_offset;
1035 KeyDataLength -= skip_offset;
1036 DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1038 else
1039 return TRUE;
1043 DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1045 // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
1046 if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
1048 if (KeyDataLength >= 8) // KDE format exclude GTK length
1050 pKDE = (PKDE_ENCAP) pMyKeyData;
1053 DefaultIdx = pKDE->GTKEncap.Kid;
1055 // Sanity check - KED length
1056 if (KeyDataLength < (pKDE->Len + 2))
1058 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1059 return FALSE;
1062 // Get GTK length - refer to IEEE 802.11i-2004 p.82
1063 GTKLEN = pKDE->Len -6;
1064 if (GTKLEN < LEN_AES_KEY)
1066 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1067 return FALSE;
1071 else
1073 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
1074 return FALSE;
1077 DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
1078 // skip it
1079 pMyKeyData += 8;
1080 KeyDataLength -= 8;
1083 else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
1085 DefaultIdx = GroupKeyIndex;
1086 DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
1089 // Sanity check - shared key index must be 1 ~ 3
1090 if (DefaultIdx < 1 || DefaultIdx > 3)
1092 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1093 return FALSE;
1097 #ifdef CONFIG_STA_SUPPORT
1098 // Todo
1099 #endif // CONFIG_STA_SUPPORT //
1101 return TRUE;
1107 ========================================================================
1109 Routine Description:
1110 Construct EAPoL message for WPA handshaking
1111 Its format is below,
1113 +--------------------+
1114 | Protocol Version | 1 octet
1115 +--------------------+
1116 | Protocol Type | 1 octet
1117 +--------------------+
1118 | Body Length | 2 octets
1119 +--------------------+
1120 | Descriptor Type | 1 octet
1121 +--------------------+
1122 | Key Information | 2 octets
1123 +--------------------+
1124 | Key Length | 1 octet
1125 +--------------------+
1126 | Key Repaly Counter | 8 octets
1127 +--------------------+
1128 | Key Nonce | 32 octets
1129 +--------------------+
1130 | Key IV | 16 octets
1131 +--------------------+
1132 | Key RSC | 8 octets
1133 +--------------------+
1134 | Key ID or Reserved | 8 octets
1135 +--------------------+
1136 | Key MIC | 16 octets
1137 +--------------------+
1138 | Key Data Length | 2 octets
1139 +--------------------+
1140 | Key Data | n octets
1141 +--------------------+
1144 Arguments:
1145 pAd Pointer to our adapter
1147 Return Value:
1148 None
1150 Note:
1152 ========================================================================
1154 VOID ConstructEapolMsg(
1155 IN PRTMP_ADAPTER pAd,
1156 IN UCHAR AuthMode,
1157 IN UCHAR WepStatus,
1158 IN UCHAR GroupKeyWepStatus,
1159 IN UCHAR MsgType,
1160 IN UCHAR DefaultKeyIdx,
1161 IN UCHAR *ReplayCounter,
1162 IN UCHAR *KeyNonce,
1163 IN UCHAR *TxRSC,
1164 IN UCHAR *PTK,
1165 IN UCHAR *GTK,
1166 IN UCHAR *RSNIE,
1167 IN UCHAR RSNIE_Len,
1168 OUT PEAPOL_PACKET pMsg)
1170 BOOLEAN bWPA2 = FALSE;
1172 // Choose WPA2 or not
1173 if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
1174 bWPA2 = TRUE;
1176 // Init Packet and Fill header
1177 pMsg->ProVer = EAPOL_VER;
1178 pMsg->ProType = EAPOLKey;
1180 // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
1181 pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
1183 // Fill in EAPoL descriptor
1184 if (bWPA2)
1185 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
1186 else
1187 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
1189 // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
1190 // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
1191 pMsg->KeyDesc.KeyInfo.KeyDescVer =
1192 (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1194 // Specify Key Type as Group(0) or Pairwise(1)
1195 if (MsgType >= EAPOL_GROUP_MSG_1)
1196 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
1197 else
1198 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1200 // Specify Key Index, only group_msg1_WPA1
1201 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
1202 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
1204 if (MsgType == EAPOL_PAIR_MSG_3)
1205 pMsg->KeyDesc.KeyInfo.Install = 1;
1207 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
1208 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
1210 if (MsgType != EAPOL_PAIR_MSG_1)
1211 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
1213 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
1215 pMsg->KeyDesc.KeyInfo.Secure = 1;
1218 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1220 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
1223 // key Information element has done.
1224 *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
1226 // Fill in Key Length
1228 if (MsgType >= EAPOL_GROUP_MSG_1)
1230 // the length of group key cipher
1231 pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
1233 else
1235 // the length of pairwise key cipher
1236 pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
1240 // Fill in replay counter
1241 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
1243 // Fill Key Nonce field
1244 // ANonce : pairwise_msg1 & pairwise_msg3
1245 // SNonce : pairwise_msg2
1246 // GNonce : group_msg1_wpa1
1247 if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
1248 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
1250 // Fill key IV - WPA2 as 0, WPA1 as random
1251 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
1253 // Suggest IV be random number plus some number,
1254 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
1255 pMsg->KeyDesc.KeyIv[15] += 2;
1258 // Fill Key RSC field
1259 // It contains the RSC for the GTK being installed.
1260 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
1262 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
1265 // Clear Key MIC field for MIC calculation later
1266 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1268 ConstructEapolKeyData(pAd,
1269 AuthMode,
1270 WepStatus,
1271 GroupKeyWepStatus,
1272 MsgType,
1273 DefaultKeyIdx,
1274 bWPA2,
1275 PTK,
1276 GTK,
1277 RSNIE,
1278 RSNIE_Len,
1279 pMsg);
1281 // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
1282 if (MsgType != EAPOL_PAIR_MSG_1)
1284 CalculateMIC(pAd, WepStatus, PTK, pMsg);
1287 DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1288 DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1]));
1289 DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1]));
1295 ========================================================================
1297 Routine Description:
1298 Construct the Key Data field of EAPoL message
1300 Arguments:
1301 pAd Pointer to our adapter
1302 Elem Message body
1304 Return Value:
1305 None
1307 Note:
1309 ========================================================================
1311 VOID ConstructEapolKeyData(
1312 IN PRTMP_ADAPTER pAd,
1313 IN UCHAR AuthMode,
1314 IN UCHAR WepStatus,
1315 IN UCHAR GroupKeyWepStatus,
1316 IN UCHAR MsgType,
1317 IN UCHAR DefaultKeyIdx,
1318 IN BOOLEAN bWPA2Capable,
1319 IN UCHAR *PTK,
1320 IN UCHAR *GTK,
1321 IN UCHAR *RSNIE,
1322 IN UCHAR RSNIE_LEN,
1323 OUT PEAPOL_PACKET pMsg)
1325 UCHAR *mpool, *Key_Data, *Rc4GTK;
1326 UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
1327 UCHAR data_offset;
1330 if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
1331 return;
1333 // allocate memory pool
1334 os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
1336 if (mpool == NULL)
1337 return;
1339 /* Rc4GTK Len = 512 */
1340 Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
1341 /* Key_Data Len = 512 */
1342 Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
1344 NdisZeroMemory(Key_Data, 512);
1345 pMsg->KeyDesc.KeyDataLen[1] = 0;
1346 data_offset = 0;
1348 // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
1349 if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
1351 if (bWPA2Capable)
1352 Key_Data[data_offset + 0] = IE_WPA2;
1353 else
1354 Key_Data[data_offset + 0] = IE_WPA;
1356 Key_Data[data_offset + 1] = RSNIE_LEN;
1357 NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
1358 data_offset += (2 + RSNIE_LEN);
1361 // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
1362 if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1364 // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h
1365 Key_Data[data_offset + 0] = 0xDD;
1367 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1369 Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
1371 else
1373 Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
1376 Key_Data[data_offset + 2] = 0x00;
1377 Key_Data[data_offset + 3] = 0x0F;
1378 Key_Data[data_offset + 4] = 0xAC;
1379 Key_Data[data_offset + 5] = 0x01;
1381 // GTK KDE format - 802.11i-2004 Figure-43x
1382 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
1383 Key_Data[data_offset + 7] = 0x00; // Reserved Byte
1385 data_offset += 8;
1389 // Encapsulate GTK and encrypt the key-data field with KEK.
1390 // Only for pairwise_msg3_WPA2 and group_msg1
1391 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
1393 // Fill in GTK
1394 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1396 NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
1397 data_offset += LEN_AES_KEY;
1399 else
1401 NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
1402 data_offset += TKIP_GTK_LENGTH;
1405 // Still dont know why, but if not append will occur "GTK not include in MSG3"
1406 // Patch for compatibility between zero config and funk
1407 if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
1409 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1411 Key_Data[data_offset + 0] = 0xDD;
1412 Key_Data[data_offset + 1] = 0;
1413 data_offset += 2;
1415 else
1417 Key_Data[data_offset + 0] = 0xDD;
1418 Key_Data[data_offset + 1] = 0;
1419 Key_Data[data_offset + 2] = 0;
1420 Key_Data[data_offset + 3] = 0;
1421 Key_Data[data_offset + 4] = 0;
1422 Key_Data[data_offset + 5] = 0;
1423 data_offset += 6;
1427 // Encrypt the data material in key data field
1428 if (WepStatus == Ndis802_11Encryption3Enabled)
1430 AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
1431 // AES wrap function will grow 8 bytes in length
1432 data_offset += 8;
1434 else
1436 // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
1437 // put TxTsc in Key RSC field
1438 pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32.
1440 // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
1441 NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
1442 NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
1443 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV)
1444 pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
1445 WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
1448 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
1450 else
1452 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
1455 // set key data length field and total length
1456 pMsg->KeyDesc.KeyDataLen[1] = data_offset;
1457 pMsg->Body_Len[1] += data_offset;
1459 os_free_mem(pAd, mpool);
1464 ========================================================================
1466 Routine Description:
1467 Calcaulate MIC. It is used during 4-ways handsharking.
1469 Arguments:
1470 pAd - pointer to our pAdapter context
1471 PeerWepStatus - indicate the encryption type
1473 Return Value:
1475 Note:
1477 ========================================================================
1479 VOID CalculateMIC(
1480 IN PRTMP_ADAPTER pAd,
1481 IN UCHAR PeerWepStatus,
1482 IN UCHAR *PTK,
1483 OUT PEAPOL_PACKET pMsg)
1485 UCHAR *OutBuffer;
1486 ULONG FrameLen = 0;
1487 UCHAR mic[LEN_KEY_DESC_MIC];
1488 UCHAR digest[80];
1490 // allocate memory for MIC calculation
1491 os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
1493 if (OutBuffer == NULL)
1495 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
1496 return;
1499 // make a frame for calculating MIC.
1500 MakeOutgoingFrame(OutBuffer, &FrameLen,
1501 pMsg->Body_Len[1] + 4, pMsg,
1502 END_OF_ARGS);
1504 NdisZeroMemory(mic, sizeof(mic));
1506 // Calculate MIC
1507 if (PeerWepStatus == Ndis802_11Encryption3Enabled)
1509 HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
1510 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
1512 else
1514 hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic);
1517 // store the calculated MIC
1518 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
1520 os_free_mem(pAd, OutBuffer);
1524 ========================================================================
1526 Routine Description:
1527 Some received frames can't decrypt by Asic, so decrypt them by software.
1529 Arguments:
1530 pAd - pointer to our pAdapter context
1531 PeerWepStatus - indicate the encryption type
1533 Return Value:
1534 NDIS_STATUS_SUCCESS - decryption successful
1535 NDIS_STATUS_FAILURE - decryption failure
1537 ========================================================================
1539 NDIS_STATUS RTMPSoftDecryptBroadCastData(
1540 IN PRTMP_ADAPTER pAd,
1541 IN RX_BLK *pRxBlk,
1542 IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
1543 IN PCIPHER_KEY pShard_key)
1545 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
1549 // handle WEP decryption
1550 if (GroupCipher == Ndis802_11Encryption1Enabled)
1552 if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
1555 //Minus IV[4] & ICV[4]
1556 pRxWI->MPDUtotalByteCount -= 8;
1558 else
1560 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
1561 // give up this frame
1562 return NDIS_STATUS_FAILURE;
1565 // handle TKIP decryption
1566 else if (GroupCipher == Ndis802_11Encryption2Enabled)
1568 if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
1571 //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
1572 pRxWI->MPDUtotalByteCount -= 20;
1574 else
1576 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
1577 // give up this frame
1578 return NDIS_STATUS_FAILURE;
1581 // handle AES decryption
1582 else if (GroupCipher == Ndis802_11Encryption3Enabled)
1584 if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
1587 //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
1588 pRxWI->MPDUtotalByteCount -= 16;
1590 else
1592 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
1593 // give up this frame
1594 return NDIS_STATUS_FAILURE;
1597 else
1599 // give up this frame
1600 return NDIS_STATUS_FAILURE;
1603 return NDIS_STATUS_SUCCESS;