2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
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. *
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. *
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. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
38 #include "../rt_config.h"
40 UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00};
41 UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01};
42 UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01};
43 UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
44 UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
45 UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05};
46 UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
47 UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
49 UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
50 UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
51 UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
52 UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
53 UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
54 UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05};
56 UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06
57 UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06
60 ========================================================================
63 The pseudo-random function(PRF) that hashes various inputs to
64 derive a pseudo-random value. To add liveness to the pseudo-random
65 value, a nonce should be one of the inputs.
67 It is used to generate PTK, GTK or some specific random value.
70 UCHAR *key, - the key material for HMAC_SHA1 use
71 INT key_len - the length of key
72 UCHAR *prefix - a prefix label
73 INT prefix_len - the length of the label
74 UCHAR *data - a specific data with variable length
75 INT data_len - the length of a specific data
76 INT len - the output lenght
79 UCHAR *output - the calculated result
82 802.11i-2004 Annex H.3
84 ========================================================================
101 // Allocate memory for input
102 os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
106 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
110 // Generate concatenation input
111 NdisMoveMemory(input, prefix, prefix_len);
113 // Concatenate a single octet containing 0
114 input[prefix_len] = 0;
116 // Concatenate specific data
117 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
118 total_len = prefix_len + 1 + data_len;
120 // Concatenate a single octet containing 0
121 // This octet shall be update later
122 input[total_len] = 0;
125 // Iterate to calculate the result by hmac-sha-1
126 // Then concatenate to last result
127 for (i = 0; i < (len + 19) / 20; i++)
129 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
132 // update the last octet
133 input[total_len - 1]++;
135 os_free_mem(NULL, input);
139 ========================================================================
142 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
143 It shall be called by 4-way handshake processing.
146 pAd - pointer to our pAdapter context
148 ANonce - pointer to ANonce
149 AA - pointer to Authenticator Address
150 SNonce - pointer to SNonce
151 SA - pointer to Supplicant Address
152 len - indicate the length of PTK (octet)
155 Output pointer to the PTK
158 Refer to IEEE 802.11i-2004 8.5.1.2
160 ========================================================================
163 IN PRTMP_ADAPTER pAd,
172 UCHAR concatenation[76];
175 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
176 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
178 // initiate the concatenation input
179 NdisZeroMemory(temp, sizeof(temp));
180 NdisZeroMemory(concatenation, 76);
182 // Get smaller address
183 if (RTMPCompareMemory(SA, AA, 6) == 1)
184 NdisMoveMemory(concatenation, AA, 6);
186 NdisMoveMemory(concatenation, SA, 6);
189 // Get larger address
190 if (RTMPCompareMemory(SA, AA, 6) == 1)
191 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
193 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
195 // store the larger mac address for backward compatible of
196 // ralink proprietary STA-key issue
197 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
201 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
202 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
203 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
204 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
206 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
210 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
211 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
212 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
213 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
215 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
218 hex_dump("concatenation=", concatenation, 76);
220 // Use PRF to generate PTK
221 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
226 ========================================================================
229 Generate random number by software.
232 pAd - pointer to our pAdapter context
233 macAddr - pointer to local MAC address
238 802.1ii-2004 Annex H.5
240 ========================================================================
243 IN PRTMP_ADAPTER pAd,
248 UCHAR local[80], KeyCounter[32];
251 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
253 // Zero the related information
254 NdisZeroMemory(result, 80);
255 NdisZeroMemory(local, 80);
256 NdisZeroMemory(KeyCounter, 32);
258 for (i = 0; i < 32; i++)
260 // copy the local MAC address
261 COPY_MAC_ADDR(local, macAddr);
264 // concatenate the current time
265 NdisGetSystemUpTime(&CurrentTime);
266 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
267 curr += sizeof(CurrentTime);
269 // concatenate the last result
270 NdisMoveMemory(&local[curr], result, 32);
273 // concatenate a variable
274 NdisMoveMemory(&local[curr], &i, 2);
277 // calculate the result
278 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
281 NdisMoveMemory(random, result, 32);
285 ========================================================================
288 Build cipher suite in RSN-IE.
289 It only shall be called by RTMPMakeRSNIE.
292 pAd - pointer to our pAdapter context
293 ElementID - indicate the WPA1 or WPA2
294 WepStatus - indicate the encryption type
295 bMixCipher - a boolean to indicate the pairwise cipher and group
296 cipher are the same or not
302 ========================================================================
304 static VOID RTMPInsertRsnIeCipher(
305 IN PRTMP_ADAPTER pAd,
308 IN BOOLEAN bMixCipher,
309 IN UCHAR FlexibleCipher,
317 // decide WPA2 or WPA1
318 if (ElementID == Wpa2Ie)
320 RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
322 // Assign the verson as 1
323 pRsnie_cipher->version = 1;
328 case Ndis802_11Encryption2Enabled:
329 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
330 pRsnie_cipher->ucount = 1;
331 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
332 *rsn_len = sizeof(RSNIE2);
336 case Ndis802_11Encryption3Enabled:
338 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
340 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
341 pRsnie_cipher->ucount = 1;
342 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
343 *rsn_len = sizeof(RSNIE2);
347 case Ndis802_11Encryption4Enabled:
348 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
351 // Insert WPA2 TKIP as the first pairwise cipher
352 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
354 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
355 // Insert WPA2 AES as the secondary pairwise cipher
356 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
358 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
364 // Insert WPA2 AES as the first pairwise cipher
365 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
368 pRsnie_cipher->ucount = PairwiseCnt;
369 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
373 #ifdef CONFIG_STA_SUPPORT
374 if ((pAd->OpMode == OPMODE_STA) &&
375 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
376 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
378 UINT GroupCipher = pAd->StaCfg.GroupCipher;
381 case Ndis802_11GroupWEP40Enabled:
382 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
384 case Ndis802_11GroupWEP104Enabled:
385 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
389 #endif // CONFIG_STA_SUPPORT //
391 // swap for big-endian platform
392 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
393 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
397 RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
399 // Assign OUI and version
400 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
401 pRsnie_cipher->version = 1;
406 case Ndis802_11Encryption2Enabled:
407 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
408 pRsnie_cipher->ucount = 1;
409 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
410 *rsn_len = sizeof(RSNIE);
414 case Ndis802_11Encryption3Enabled:
416 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
418 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
419 pRsnie_cipher->ucount = 1;
420 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
421 *rsn_len = sizeof(RSNIE);
425 case Ndis802_11Encryption4Enabled:
426 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
429 // Insert WPA TKIP as the first pairwise cipher
430 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
432 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
433 // Insert WPA AES as the secondary pairwise cipher
434 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
436 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
442 // Insert WPA AES as the first pairwise cipher
443 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
446 pRsnie_cipher->ucount = PairwiseCnt;
447 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
451 #ifdef CONFIG_STA_SUPPORT
452 if ((pAd->OpMode == OPMODE_STA) &&
453 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
454 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
456 UINT GroupCipher = pAd->StaCfg.GroupCipher;
459 case Ndis802_11GroupWEP40Enabled:
460 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
462 case Ndis802_11GroupWEP104Enabled:
463 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
467 #endif // CONFIG_STA_SUPPORT //
469 // swap for big-endian platform
470 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
471 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
476 ========================================================================
479 Build AKM suite in RSN-IE.
480 It only shall be called by RTMPMakeRSNIE.
483 pAd - pointer to our pAdapter context
484 ElementID - indicate the WPA1 or WPA2
485 AuthMode - indicate the authentication mode
486 apidx - indicate the interface index
492 ========================================================================
494 static VOID RTMPInsertRsnIeAKM(
495 IN PRTMP_ADAPTER pAd,
502 RSNIE_AUTH *pRsnie_auth;
504 pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
506 // decide WPA2 or WPA1
507 if (ElementID == Wpa2Ie)
511 case Ndis802_11AuthModeWPA2:
512 case Ndis802_11AuthModeWPA1WPA2:
513 pRsnie_auth->acount = 1;
514 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
517 case Ndis802_11AuthModeWPA2PSK:
518 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
519 pRsnie_auth->acount = 1;
520 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
528 case Ndis802_11AuthModeWPA:
529 case Ndis802_11AuthModeWPA1WPA2:
530 pRsnie_auth->acount = 1;
531 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
534 case Ndis802_11AuthModeWPAPSK:
535 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
536 pRsnie_auth->acount = 1;
537 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
540 case Ndis802_11AuthModeWPANone:
541 pRsnie_auth->acount = 1;
542 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
547 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
549 (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length
554 ========================================================================
557 Build capability in RSN-IE.
558 It only shall be called by RTMPMakeRSNIE.
561 pAd - pointer to our pAdapter context
562 ElementID - indicate the WPA1 or WPA2
563 apidx - indicate the interface index
569 ========================================================================
571 static VOID RTMPInsertRsnIeCap(
572 IN PRTMP_ADAPTER pAd,
578 RSN_CAPABILITIES *pRSN_Cap;
580 // it could be ignored in WPA1 mode
581 if (ElementID == WpaIe)
584 pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
587 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
589 (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
595 ========================================================================
598 Build RSN IE context. It is not included element-ID and length.
601 pAd - pointer to our pAdapter context
602 AuthMode - indicate the authentication mode
603 WepStatus - indicate the encryption type
604 apidx - indicate the interface index
610 ========================================================================
613 IN PRTMP_ADAPTER pAd,
618 PUCHAR pRsnIe = NULL; // primary RSNIE
619 UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE
620 UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
622 BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
624 WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
626 rsnielen_cur_p = NULL;
627 rsnielen_ex_cur_p = NULL;
630 #ifdef CONFIG_STA_SUPPORT
631 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
633 #ifdef WPA_SUPPLICANT_SUPPORT
634 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
636 if (AuthMode < Ndis802_11AuthModeWPA)
640 #endif // WPA_SUPPLICANT_SUPPORT //
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)
651 DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
653 // Zero RSNIE context
654 pAd->StaCfg.RSNIE_Len = 0;
655 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
658 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
659 pRsnIe = pAd->StaCfg.RSN_IE;
661 bMixCipher = pAd->StaCfg.bMixCipher;
663 #endif // CONFIG_STA_SUPPORT //
666 // indicate primary RSNIE as WPA or WPA2
667 if ((AuthMode == Ndis802_11AuthModeWPA) ||
668 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
669 (AuthMode == Ndis802_11AuthModeWPANone) ||
670 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
671 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
672 PrimaryRsnie = WpaIe;
674 PrimaryRsnie = Wpa2Ie;
677 // Build the primary RSNIE
678 // 1. insert cipher suite
679 RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
682 RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
684 // 3. insert capability
685 RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
688 // 4. update the RSNIE length
689 *rsnielen_cur_p = p_offset;
691 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
697 ==========================================================================
699 Check whether the received frame is EAP frame.
702 pAd - pointer to our pAdapter context
703 pEntry - pointer to active entry
704 pData - the received frame
705 DataByteCount - the received frame's length
706 FromWhichBSSID - indicate the interface index
709 TRUE - This frame is EAP frame
711 ==========================================================================
713 BOOLEAN RTMPCheckWPAframe(
714 IN PRTMP_ADAPTER pAd,
715 IN PMAC_TABLE_ENTRY pEntry,
717 IN ULONG DataByteCount,
718 IN UCHAR FromWhichBSSID)
724 if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
729 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
730 // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
731 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
735 // Skip 2-bytes EAPoL type
736 if (NdisEqualMemory(EAPOL, pData, 2))
746 Body_len = (*(pData+2)<<8) | (*(pData+3));
747 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
750 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
751 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
753 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
754 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
755 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
759 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
762 Body_len = (*(pData+2)<<8) | (*(pData+3));
763 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
766 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
777 ==========================================================================
779 ENCRYPT AES GTK before sending in EAPOL frame.
780 AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function.
781 This function references to RFC 3394 for aes key wrap algorithm.
783 ==========================================================================
785 VOID AES_GTK_KEY_WRAP(
789 OUT UCHAR *ciphertext)
791 UCHAR A[8], BIN[16], BOUT[16];
793 INT num_blocks = p_len/8; // unit:64bits
798 rtmp_aes_set_key(&aesctx, key, 128);
801 for (i = 0; i < 8; i++)
805 for (i = 0; i < num_blocks; i++)
807 for (j = 0 ; j < 8; j++)
808 R[8 * (i + 1) + j] = plaintext[8 * i + j];
812 for (j = 0; j < 6; j++)
814 for(i = 1; i <= num_blocks; i++)
817 NdisMoveMemory(BIN, A, 8);
818 NdisMoveMemory(&BIN[8], &R[8 * i], 8);
819 rtmp_aes_encrypt(&aesctx, BIN, BOUT);
821 NdisMoveMemory(A, &BOUT[0], 8);
822 xor = num_blocks * j + i;
823 A[7] = BOUT[7] ^ xor;
824 NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
829 NdisMoveMemory(ciphertext, A, 8);
831 for (i = 1; i <= num_blocks; i++)
833 for (j = 0 ; j < 8; j++)
834 ciphertext[8 * i + j] = R[8 * i + j];
840 ========================================================================
843 Misc function to decrypt AES body
850 This function references to RFC 3394 for aes key unwrap algorithm.
852 ========================================================================
854 VOID AES_GTK_KEY_UNWRAP(
856 OUT UCHAR *plaintext,
858 IN UCHAR *ciphertext)
861 UCHAR A[8], BIN[16], BOUT[16];
866 INT num_blocks = c_len/8; // unit:64bits
869 os_alloc_mem(NULL, (PUCHAR *)&R, 512);
873 DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
878 NdisMoveMemory(A, ciphertext, 8);
880 for(i = 0; i < (c_len-8); i++)
882 R[ i] = ciphertext[i + 8];
885 rtmp_aes_set_key(&aesctx, key, 128);
887 for(j = 5; j >= 0; j--)
889 for(i = (num_blocks-1); i > 0; i--)
891 xor = (num_blocks -1 )* j + i;
892 NdisMoveMemory(BIN, A, 8);
894 NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
895 rtmp_aes_decrypt(&aesctx, BIN, BOUT);
896 NdisMoveMemory(A, &BOUT[0], 8);
897 NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
902 for(i = 0; i < c_len; i++)
908 os_free_mem(NULL, R);
912 ==========================================================================
914 Report the EAP message type
917 msg - EAPOL_PAIR_MSG_1
927 ==========================================================================
929 CHAR *GetEapolMsgType(CHAR msg)
931 if(msg == EAPOL_PAIR_MSG_1)
932 return "Pairwise Message 1";
933 else if(msg == EAPOL_PAIR_MSG_2)
934 return "Pairwise Message 2";
935 else if(msg == EAPOL_PAIR_MSG_3)
936 return "Pairwise Message 3";
937 else if(msg == EAPOL_PAIR_MSG_4)
938 return "Pairwise Message 4";
939 else if(msg == EAPOL_GROUP_MSG_1)
940 return "Group Message 1";
941 else if(msg == EAPOL_GROUP_MSG_2)
942 return "Group Message 2";
944 return "Invalid Message";
949 ========================================================================
952 Check Sanity RSN IE of EAPoL message
959 ========================================================================
961 BOOLEAN RTMPCheckRSNIE(
962 IN PRTMP_ADAPTER pAd,
965 IN MAC_TABLE_ENTRY *pEntry,
971 BOOLEAN result = FALSE;
977 while (len > sizeof(RSNIE2))
979 pEid = (PEID_STRUCT) pVIE;
981 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
983 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
984 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
985 (pEntry->RSNIE_Len == (pEid->Len + 2)))
990 *Offset += (pEid->Len + 2);
993 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
995 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
996 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
997 (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
1002 *Offset += (pEid->Len + 2);
1009 pVIE += (pEid->Len + 2);
1010 len -= (pEid->Len + 2);
1020 ========================================================================
1022 Routine Description:
1023 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
1024 GTK is encaptulated in KDE format at p.83 802.11i D10
1033 ========================================================================
1035 BOOLEAN RTMPParseEapolKeyData(
1036 IN PRTMP_ADAPTER pAd,
1038 IN UCHAR KeyDataLen,
1039 IN UCHAR GroupKeyIndex,
1042 IN MAC_TABLE_ENTRY *pEntry)
1044 PKDE_ENCAP pKDE = NULL;
1045 PUCHAR pMyKeyData = pKeyData;
1046 UCHAR KeyDataLength = KeyDataLen;
1048 UCHAR DefaultIdx = 0;
1051 // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
1052 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
1054 // Check RSN IE whether it is WPA2/WPA2PSK
1055 if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
1057 // send wireless event - for RSN IE different
1058 if (pAd->CommonCfg.bWirelessEvent)
1059 RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1061 DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
1062 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
1063 hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
1069 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
1072 pMyKeyData += skip_offset;
1073 KeyDataLength -= skip_offset;
1074 DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1081 DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1083 // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
1084 if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
1086 if (KeyDataLength >= 8) // KDE format exclude GTK length
1088 pKDE = (PKDE_ENCAP) pMyKeyData;
1091 DefaultIdx = pKDE->GTKEncap.Kid;
1093 // Sanity check - KED length
1094 if (KeyDataLength < (pKDE->Len + 2))
1096 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1100 // Get GTK length - refer to IEEE 802.11i-2004 p.82
1101 GTKLEN = pKDE->Len -6;
1102 if (GTKLEN < LEN_AES_KEY)
1104 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1111 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
1115 DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
1121 else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
1123 DefaultIdx = GroupKeyIndex;
1124 DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
1127 // Sanity check - shared key index must be 1 ~ 3
1128 if (DefaultIdx < 1 || DefaultIdx > 3)
1130 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1135 #ifdef CONFIG_STA_SUPPORT
1137 #endif // CONFIG_STA_SUPPORT //
1145 ========================================================================
1147 Routine Description:
1148 Construct EAPoL message for WPA handshaking
1149 Its format is below,
1151 +--------------------+
1152 | Protocol Version | 1 octet
1153 +--------------------+
1154 | Protocol Type | 1 octet
1155 +--------------------+
1156 | Body Length | 2 octets
1157 +--------------------+
1158 | Descriptor Type | 1 octet
1159 +--------------------+
1160 | Key Information | 2 octets
1161 +--------------------+
1162 | Key Length | 1 octet
1163 +--------------------+
1164 | Key Repaly Counter | 8 octets
1165 +--------------------+
1166 | Key Nonce | 32 octets
1167 +--------------------+
1168 | Key IV | 16 octets
1169 +--------------------+
1170 | Key RSC | 8 octets
1171 +--------------------+
1172 | Key ID or Reserved | 8 octets
1173 +--------------------+
1174 | Key MIC | 16 octets
1175 +--------------------+
1176 | Key Data Length | 2 octets
1177 +--------------------+
1178 | Key Data | n octets
1179 +--------------------+
1183 pAd Pointer to our adapter
1190 ========================================================================
1192 VOID ConstructEapolMsg(
1193 IN PRTMP_ADAPTER pAd,
1196 IN UCHAR GroupKeyWepStatus,
1198 IN UCHAR DefaultKeyIdx,
1199 IN UCHAR *ReplayCounter,
1206 OUT PEAPOL_PACKET pMsg)
1208 BOOLEAN bWPA2 = FALSE;
1210 // Choose WPA2 or not
1211 if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
1214 // Init Packet and Fill header
1215 pMsg->ProVer = EAPOL_VER;
1216 pMsg->ProType = EAPOLKey;
1218 // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
1219 pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
1221 // Fill in EAPoL descriptor
1223 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
1225 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
1227 // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
1228 // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
1229 pMsg->KeyDesc.KeyInfo.KeyDescVer =
1230 (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1232 // Specify Key Type as Group(0) or Pairwise(1)
1233 if (MsgType >= EAPOL_GROUP_MSG_1)
1234 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
1236 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1238 // Specify Key Index, only group_msg1_WPA1
1239 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
1240 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
1242 if (MsgType == EAPOL_PAIR_MSG_3)
1243 pMsg->KeyDesc.KeyInfo.Install = 1;
1245 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
1246 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
1248 if (MsgType != EAPOL_PAIR_MSG_1)
1249 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
1251 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
1253 pMsg->KeyDesc.KeyInfo.Secure = 1;
1256 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1258 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
1261 // key Information element has done.
1262 *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
1264 // Fill in Key Length
1266 if (MsgType >= EAPOL_GROUP_MSG_1)
1268 // the length of group key cipher
1269 pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
1273 // the length of pairwise key cipher
1274 pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
1278 // Fill in replay counter
1279 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
1281 // Fill Key Nonce field
1282 // ANonce : pairwise_msg1 & pairwise_msg3
1283 // SNonce : pairwise_msg2
1284 // GNonce : group_msg1_wpa1
1285 if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
1286 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
1288 // Fill key IV - WPA2 as 0, WPA1 as random
1289 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
1291 // Suggest IV be random number plus some number,
1292 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
1293 pMsg->KeyDesc.KeyIv[15] += 2;
1296 // Fill Key RSC field
1297 // It contains the RSC for the GTK being installed.
1298 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
1300 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
1303 // Clear Key MIC field for MIC calculation later
1304 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1306 ConstructEapolKeyData(pAd,
1319 // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
1320 if (MsgType != EAPOL_PAIR_MSG_1)
1322 CalculateMIC(pAd, WepStatus, PTK, pMsg);
1325 DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1326 DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1]));
1327 DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1]));
1333 ========================================================================
1335 Routine Description:
1336 Construct the Key Data field of EAPoL message
1339 pAd Pointer to our adapter
1347 ========================================================================
1349 VOID ConstructEapolKeyData(
1350 IN PRTMP_ADAPTER pAd,
1353 IN UCHAR GroupKeyWepStatus,
1355 IN UCHAR DefaultKeyIdx,
1356 IN BOOLEAN bWPA2Capable,
1361 OUT PEAPOL_PACKET pMsg)
1363 UCHAR *mpool, *Key_Data, *Rc4GTK;
1364 UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
1368 if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
1371 // allocate memory pool
1372 os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
1377 /* Rc4GTK Len = 512 */
1378 Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
1379 /* Key_Data Len = 512 */
1380 Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
1382 NdisZeroMemory(Key_Data, 512);
1383 pMsg->KeyDesc.KeyDataLen[1] = 0;
1386 // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
1387 if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
1390 Key_Data[data_offset + 0] = IE_WPA2;
1392 Key_Data[data_offset + 0] = IE_WPA;
1394 Key_Data[data_offset + 1] = RSNIE_LEN;
1395 NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
1396 data_offset += (2 + RSNIE_LEN);
1399 // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
1400 if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1402 // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h
1403 Key_Data[data_offset + 0] = 0xDD;
1405 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1407 Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
1411 Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
1414 Key_Data[data_offset + 2] = 0x00;
1415 Key_Data[data_offset + 3] = 0x0F;
1416 Key_Data[data_offset + 4] = 0xAC;
1417 Key_Data[data_offset + 5] = 0x01;
1419 // GTK KDE format - 802.11i-2004 Figure-43x
1420 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
1421 Key_Data[data_offset + 7] = 0x00; // Reserved Byte
1427 // Encapsulate GTK and encrypt the key-data field with KEK.
1428 // Only for pairwise_msg3_WPA2 and group_msg1
1429 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
1432 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1434 NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
1435 data_offset += LEN_AES_KEY;
1439 NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
1440 data_offset += TKIP_GTK_LENGTH;
1443 // Still dont know why, but if not append will occur "GTK not include in MSG3"
1444 // Patch for compatibility between zero config and funk
1445 if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
1447 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1449 Key_Data[data_offset + 0] = 0xDD;
1450 Key_Data[data_offset + 1] = 0;
1455 Key_Data[data_offset + 0] = 0xDD;
1456 Key_Data[data_offset + 1] = 0;
1457 Key_Data[data_offset + 2] = 0;
1458 Key_Data[data_offset + 3] = 0;
1459 Key_Data[data_offset + 4] = 0;
1460 Key_Data[data_offset + 5] = 0;
1465 // Encrypt the data material in key data field
1466 if (WepStatus == Ndis802_11Encryption3Enabled)
1468 AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
1469 // AES wrap function will grow 8 bytes in length
1474 // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
1475 // put TxTsc in Key RSC field
1476 pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32.
1478 // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
1479 NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
1480 NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
1481 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV)
1482 pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
1483 WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
1486 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
1490 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
1493 // set key data length field and total length
1494 pMsg->KeyDesc.KeyDataLen[1] = data_offset;
1495 pMsg->Body_Len[1] += data_offset;
1497 os_free_mem(pAd, mpool);
1502 ========================================================================
1504 Routine Description:
1505 Calcaulate MIC. It is used during 4-ways handsharking.
1508 pAd - pointer to our pAdapter context
1509 PeerWepStatus - indicate the encryption type
1515 ========================================================================
1518 IN PRTMP_ADAPTER pAd,
1519 IN UCHAR PeerWepStatus,
1521 OUT PEAPOL_PACKET pMsg)
1525 UCHAR mic[LEN_KEY_DESC_MIC];
1528 // allocate memory for MIC calculation
1529 os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
1531 if (OutBuffer == NULL)
1533 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
1537 // make a frame for calculating MIC.
1538 MakeOutgoingFrame(OutBuffer, &FrameLen,
1539 pMsg->Body_Len[1] + 4, pMsg,
1542 NdisZeroMemory(mic, sizeof(mic));
1545 if (PeerWepStatus == Ndis802_11Encryption3Enabled)
1547 HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
1548 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
1552 hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic);
1555 // store the calculated MIC
1556 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
1558 os_free_mem(pAd, OutBuffer);
1562 ========================================================================
1564 Routine Description:
1565 Some received frames can't decrypt by Asic, so decrypt them by software.
1568 pAd - pointer to our pAdapter context
1569 PeerWepStatus - indicate the encryption type
1572 NDIS_STATUS_SUCCESS - decryption successful
1573 NDIS_STATUS_FAILURE - decryption failure
1575 ========================================================================
1577 NDIS_STATUS RTMPSoftDecryptBroadCastData(
1578 IN PRTMP_ADAPTER pAd,
1580 IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
1581 IN PCIPHER_KEY pShard_key)
1583 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
1587 // handle WEP decryption
1588 if (GroupCipher == Ndis802_11Encryption1Enabled)
1590 if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
1593 //Minus IV[4] & ICV[4]
1594 pRxWI->MPDUtotalByteCount -= 8;
1598 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
1599 // give up this frame
1600 return NDIS_STATUS_FAILURE;
1603 // handle TKIP decryption
1604 else if (GroupCipher == Ndis802_11Encryption2Enabled)
1606 if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
1609 //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
1610 pRxWI->MPDUtotalByteCount -= 20;
1614 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
1615 // give up this frame
1616 return NDIS_STATUS_FAILURE;
1619 // handle AES decryption
1620 else if (GroupCipher == Ndis802_11Encryption3Enabled)
1622 if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
1625 //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
1626 pRxWI->MPDUtotalByteCount -= 16;
1630 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
1631 // give up this frame
1632 return NDIS_STATUS_FAILURE;
1637 // give up this frame
1638 return NDIS_STATUS_FAILURE;
1641 return NDIS_STATUS_SUCCESS;