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_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};
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};
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 ========================================================================
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.
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
76 UCHAR *output - the calculated result
79 802.11i-2004 Annex H.3
81 ========================================================================
98 // Allocate memory for input
99 os_alloc_mem(NULL
, (PUCHAR
*)&input
, 1024);
103 DBGPRINT(RT_DEBUG_ERROR
, ("!!!PRF: no memory!!!\n"));
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;
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
]);
129 // update the last octet
130 input
[total_len
- 1]++;
132 os_free_mem(NULL
, input
);
136 ========================================================================
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.
143 pAd - pointer to our pAdapter context
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)
152 Output pointer to the PTK
155 Refer to IEEE 802.11i-2004 8.5.1.2
157 ========================================================================
160 IN PRTMP_ADAPTER pAd
,
169 UCHAR concatenation
[76];
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);
183 NdisMoveMemory(concatenation
, SA
, 6);
186 // Get larger address
187 if (RTMPCompareMemory(SA
, AA
, 6) == 1)
188 NdisMoveMemory(&concatenation
[CurrPos
], SA
, 6);
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
);
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);
203 NdisMoveMemory(&concatenation
[CurrPos
], ANonce
, 32);
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);
212 NdisMoveMemory(&concatenation
[CurrPos
], SNonce
, 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 ========================================================================
226 Generate random number by software.
229 pAd - pointer to our pAdapter context
230 macAddr - pointer to local MAC address
235 802.1ii-2004 Annex H.5
237 ========================================================================
240 IN PRTMP_ADAPTER pAd
,
245 UCHAR local
[80], KeyCounter
[32];
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
);
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);
270 // concatenate a variable
271 NdisMoveMemory(&local
[curr
], &i
, 2);
274 // calculate the result
275 PRF(KeyCounter
, 32, prefix
,12, local
, curr
, result
, 32);
278 NdisMoveMemory(random
, result
, 32);
282 ========================================================================
285 Build cipher suite in RSN-IE.
286 It only shall be called by RTMPMakeRSNIE.
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
299 ========================================================================
301 static VOID
RTMPInsertRsnIeCipher(
302 IN PRTMP_ADAPTER pAd
,
305 IN BOOLEAN bMixCipher
,
306 IN UCHAR FlexibleCipher
,
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;
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
);
333 case Ndis802_11Encryption3Enabled
:
335 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA2_TKIP
, 4);
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
);
344 case Ndis802_11Encryption4Enabled
:
345 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA2_TKIP
, 4);
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);
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));
370 // swap for big-endian platform
371 pRsnie_cipher
->version
= cpu2le16(pRsnie_cipher
->version
);
372 pRsnie_cipher
->ucount
= cpu2le16(pRsnie_cipher
->ucount
);
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;
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
);
393 case Ndis802_11Encryption3Enabled
:
395 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_TKIP
, 4);
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
);
404 case Ndis802_11Encryption4Enabled
:
405 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_TKIP
, 4);
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);
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));
430 // swap for big-endian platform
431 pRsnie_cipher
->version
= cpu2le16(pRsnie_cipher
->version
);
432 pRsnie_cipher
->ucount
= cpu2le16(pRsnie_cipher
->ucount
);
438 ========================================================================
441 Build AKM suite in RSN-IE.
442 It only shall be called by RTMPMakeRSNIE.
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
454 ========================================================================
456 static VOID
RTMPInsertRsnIeAKM(
457 IN PRTMP_ADAPTER pAd
,
464 RSNIE_AUTH
*pRsnie_auth
;
466 pRsnie_auth
= (RSNIE_AUTH
*)(pRsnIe
+ (*rsn_len
));
468 // decide WPA2 or WPA1
469 if (ElementID
== Wpa2Ie
)
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);
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);
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);
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);
502 case Ndis802_11AuthModeWPANone
:
503 pRsnie_auth
->acount
= 1;
504 NdisMoveMemory(pRsnie_auth
->auth
[0].oui
, OUI_WPA_NONE_AKM
, 4);
509 pRsnie_auth
->acount
= cpu2le16(pRsnie_auth
->acount
);
511 (*rsn_len
) += sizeof(RSNIE_AUTH
); // update current RSNIE length
516 ========================================================================
519 Build capability in RSN-IE.
520 It only shall be called by RTMPMakeRSNIE.
523 pAd - pointer to our pAdapter context
524 ElementID - indicate the WPA1 or WPA2
525 apidx - indicate the interface index
531 ========================================================================
533 static VOID
RTMPInsertRsnIeCap(
534 IN PRTMP_ADAPTER pAd
,
540 RSN_CAPABILITIES
*pRSN_Cap
;
542 // it could be ignored in WPA1 mode
543 if (ElementID
== WpaIe
)
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 ========================================================================
560 Build RSN IE context. It is not included element-ID and length.
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
572 ========================================================================
575 IN PRTMP_ADAPTER pAd
,
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
584 BOOLEAN bMixCipher
= FALSE
; // indicate the pairwise and group cipher are different
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
)
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
)
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
);
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
;
636 PrimaryRsnie
= Wpa2Ie
;
639 // Build the primary RSNIE
640 // 1. insert cipher suite
641 RTMPInsertRsnIeCipher(pAd
, PrimaryRsnie
, WepStatus
, bMixCipher
, FlexibleCipher
, pRsnIe
, &p_offset
);
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 ==========================================================================
661 Check whether the received frame is EAP frame.
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
671 TRUE - This frame is EAP frame
673 ==========================================================================
675 BOOLEAN
RTMPCheckWPAframe(
676 IN PRTMP_ADAPTER pAd
,
677 IN PMAC_TABLE_ENTRY pEntry
,
679 IN ULONG DataByteCount
,
680 IN UCHAR FromWhichBSSID
)
686 if(DataByteCount
< (LENGTH_802_1_H
+ LENGTH_EAPOL_H
))
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))
697 // Skip 2-bytes EAPoL type
698 if (NdisEqualMemory(EAPOL
, pData
, 2))
708 Body_len
= (*(pData
+2)<<8) | (*(pData
+3));
709 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len
));
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
;
721 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
724 Body_len
= (*(pData
+2)<<8) | (*(pData
+3));
725 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len
));
728 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
739 ==========================================================================
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.
745 ==========================================================================
747 VOID
AES_GTK_KEY_WRAP(
751 OUT UCHAR
*ciphertext
)
753 UCHAR A
[8], BIN
[16], BOUT
[16];
755 INT num_blocks
= p_len
/8; // unit:64bits
760 rtmp_aes_set_key(&aesctx
, key
, 128);
763 for (i
= 0; i
< 8; i
++)
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
];
774 for (j
= 0; j
< 6; j
++)
776 for(i
= 1; i
<= num_blocks
; i
++)
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);
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 ========================================================================
805 Misc function to decrypt AES body
812 This function references to RFC 3394 for aes key unwrap algorithm.
814 ========================================================================
816 VOID
AES_GTK_KEY_UNWRAP(
818 OUT UCHAR
*plaintext
,
820 IN UCHAR
*ciphertext
)
823 UCHAR A
[8], BIN
[16], BOUT
[16];
828 INT num_blocks
= c_len
/8; // unit:64bits
831 os_alloc_mem(NULL
, (PUCHAR
*)&R
, 512);
835 DBGPRINT(RT_DEBUG_ERROR
, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
840 NdisMoveMemory(A
, ciphertext
, 8);
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);
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);
864 for(i
= 0; i
< c_len
; i
++)
870 os_free_mem(NULL
, R
);
874 ==========================================================================
876 Report the EAP message type
879 msg - EAPOL_PAIR_MSG_1
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";
906 return "Invalid Message";
911 ========================================================================
914 Check Sanity RSN IE of EAPoL message
921 ========================================================================
923 BOOLEAN
RTMPCheckRSNIE(
924 IN PRTMP_ADAPTER pAd
,
927 IN MAC_TABLE_ENTRY
*pEntry
,
933 BOOLEAN result
= FALSE
;
939 while (len
> sizeof(RSNIE2
))
941 pEid
= (PEID_STRUCT
) pVIE
;
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)))
952 *Offset
+= (pEid
->Len
+ 2);
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*/)
964 *Offset
+= (pEid
->Len
+ 2);
971 pVIE
+= (pEid
->Len
+ 2);
972 len
-= (pEid
->Len
+ 2);
982 ========================================================================
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
995 ========================================================================
997 BOOLEAN
RTMPParseEapolKeyData(
998 IN PRTMP_ADAPTER pAd
,
1000 IN UCHAR KeyDataLen
,
1001 IN UCHAR GroupKeyIndex
,
1004 IN MAC_TABLE_ENTRY
*pEntry
)
1006 PKDE_ENCAP pKDE
= NULL
;
1007 PUCHAR pMyKeyData
= pKeyData
;
1008 UCHAR KeyDataLength
= KeyDataLen
;
1010 UCHAR DefaultIdx
= 0;
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
);
1031 if (bWPA2
&& MsgType
== EAPOL_PAIR_MSG_3
)
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
));
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"));
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
));
1073 DBGPRINT(RT_DEBUG_ERROR
, ("ERROR: KDE format length is too short \n"));
1077 DBGPRINT(RT_DEBUG_TRACE
, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx
, GTKLEN
));
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
)));
1097 #ifdef CONFIG_STA_SUPPORT
1099 #endif // CONFIG_STA_SUPPORT //
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 +--------------------+
1145 pAd Pointer to our adapter
1152 ========================================================================
1154 VOID
ConstructEapolMsg(
1155 IN PRTMP_ADAPTER pAd
,
1158 IN UCHAR GroupKeyWepStatus
,
1160 IN UCHAR DefaultKeyIdx
,
1161 IN UCHAR
*ReplayCounter
,
1168 OUT PEAPOL_PACKET pMsg
)
1170 BOOLEAN bWPA2
= FALSE
;
1172 // Choose WPA2 or not
1173 if ((AuthMode
== Ndis802_11AuthModeWPA2
) || (AuthMode
== Ndis802_11AuthModeWPA2PSK
))
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
1185 pMsg
->KeyDesc
.Type
= WPA2_KEY_DESC
;
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
;
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
);
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
,
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
1301 pAd Pointer to our adapter
1309 ========================================================================
1311 VOID
ConstructEapolKeyData(
1312 IN PRTMP_ADAPTER pAd
,
1315 IN UCHAR GroupKeyWepStatus
,
1317 IN UCHAR DefaultKeyIdx
,
1318 IN BOOLEAN bWPA2Capable
,
1323 OUT PEAPOL_PACKET pMsg
)
1325 UCHAR
*mpool
, *Key_Data
, *Rc4GTK
;
1326 UCHAR ekey
[(LEN_KEY_DESC_IV
+LEN_EAP_EK
)];
1330 if (MsgType
== EAPOL_PAIR_MSG_1
|| MsgType
== EAPOL_PAIR_MSG_4
|| MsgType
== EAPOL_GROUP_MSG_2
)
1333 // allocate memory pool
1334 os_alloc_mem(pAd
, (PUCHAR
*)&mpool
, 1500);
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;
1348 // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
1349 if (RSNIE_LEN
&& ((MsgType
== EAPOL_PAIR_MSG_2
) || (MsgType
== EAPOL_PAIR_MSG_3
)))
1352 Key_Data
[data_offset
+ 0] = IE_WPA2
;
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)
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
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
))
1394 if (GroupKeyWepStatus
== Ndis802_11Encryption3Enabled
)
1396 NdisMoveMemory(&Key_Data
[data_offset
], GTK
, LEN_AES_KEY
);
1397 data_offset
+= LEN_AES_KEY
;
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;
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;
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
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
);
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.
1470 pAd - pointer to our pAdapter context
1471 PeerWepStatus - indicate the encryption type
1477 ========================================================================
1480 IN PRTMP_ADAPTER pAd
,
1481 IN UCHAR PeerWepStatus
,
1483 OUT PEAPOL_PACKET pMsg
)
1487 UCHAR mic
[LEN_KEY_DESC_MIC
];
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"));
1499 // make a frame for calculating MIC.
1500 MakeOutgoingFrame(OutBuffer
, &FrameLen
,
1501 pMsg
->Body_Len
[1] + 4, pMsg
,
1504 NdisZeroMemory(mic
, sizeof(mic
));
1507 if (PeerWepStatus
== Ndis802_11Encryption3Enabled
)
1509 HMAC_SHA1(OutBuffer
, FrameLen
, PTK
, LEN_EAP_MICK
, digest
);
1510 NdisMoveMemory(mic
, digest
, LEN_KEY_DESC_MIC
);
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.
1530 pAd - pointer to our pAdapter context
1531 PeerWepStatus - indicate the encryption type
1534 NDIS_STATUS_SUCCESS - decryption successful
1535 NDIS_STATUS_FAILURE - decryption failure
1537 ========================================================================
1539 NDIS_STATUS
RTMPSoftDecryptBroadCastData(
1540 IN PRTMP_ADAPTER pAd
,
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;
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;
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;
1592 DBGPRINT(RT_DEBUG_ERROR
, ("ERROR : RTMPSoftDecryptAES Failed\n"));
1593 // give up this frame
1594 return NDIS_STATUS_FAILURE
;
1599 // give up this frame
1600 return NDIS_STATUS_FAILURE
;
1603 return NDIS_STATUS_SUCCESS
;