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 if ((pAd
->OpMode
== OPMODE_STA
) &&
374 (pAd
->StaCfg
.GroupCipher
!= Ndis802_11Encryption2Enabled
) &&
375 (pAd
->StaCfg
.GroupCipher
!= Ndis802_11Encryption3Enabled
))
377 UINT GroupCipher
= pAd
->StaCfg
.GroupCipher
;
380 case Ndis802_11GroupWEP40Enabled
:
381 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA2_WEP40
, 4);
383 case Ndis802_11GroupWEP104Enabled
:
384 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA2_WEP104
, 4);
389 // swap for big-endian platform
390 pRsnie_cipher
->version
= cpu2le16(pRsnie_cipher
->version
);
391 pRsnie_cipher
->ucount
= cpu2le16(pRsnie_cipher
->ucount
);
395 RSNIE
*pRsnie_cipher
= (RSNIE
*)pRsnIe
;
397 // Assign OUI and version
398 NdisMoveMemory(pRsnie_cipher
->oui
, OUI_WPA_VERSION
, 4);
399 pRsnie_cipher
->version
= 1;
404 case Ndis802_11Encryption2Enabled
:
405 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_TKIP
, 4);
406 pRsnie_cipher
->ucount
= 1;
407 NdisMoveMemory(pRsnie_cipher
->ucast
[0].oui
, OUI_WPA_TKIP
, 4);
408 *rsn_len
= sizeof(RSNIE
);
412 case Ndis802_11Encryption3Enabled
:
414 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_TKIP
, 4);
416 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_CCMP
, 4);
417 pRsnie_cipher
->ucount
= 1;
418 NdisMoveMemory(pRsnie_cipher
->ucast
[0].oui
, OUI_WPA_CCMP
, 4);
419 *rsn_len
= sizeof(RSNIE
);
423 case Ndis802_11Encryption4Enabled
:
424 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_TKIP
, 4);
427 // Insert WPA TKIP as the first pairwise cipher
428 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher
))
430 NdisMoveMemory(pRsnie_cipher
->ucast
[0].oui
, OUI_WPA_TKIP
, 4);
431 // Insert WPA AES as the secondary pairwise cipher
432 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher
))
434 NdisMoveMemory(pRsnie_cipher
->ucast
[0].oui
+ 4, OUI_WPA_CCMP
, 4);
440 // Insert WPA AES as the first pairwise cipher
441 NdisMoveMemory(pRsnie_cipher
->ucast
[0].oui
, OUI_WPA_CCMP
, 4);
444 pRsnie_cipher
->ucount
= PairwiseCnt
;
445 *rsn_len
= sizeof(RSNIE
) + (4 * (PairwiseCnt
- 1));
449 if ((pAd
->OpMode
== OPMODE_STA
) &&
450 (pAd
->StaCfg
.GroupCipher
!= Ndis802_11Encryption2Enabled
) &&
451 (pAd
->StaCfg
.GroupCipher
!= Ndis802_11Encryption3Enabled
))
453 UINT GroupCipher
= pAd
->StaCfg
.GroupCipher
;
456 case Ndis802_11GroupWEP40Enabled
:
457 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_WEP40
, 4);
459 case Ndis802_11GroupWEP104Enabled
:
460 NdisMoveMemory(pRsnie_cipher
->mcast
, OUI_WPA_WEP104
, 4);
465 // swap for big-endian platform
466 pRsnie_cipher
->version
= cpu2le16(pRsnie_cipher
->version
);
467 pRsnie_cipher
->ucount
= cpu2le16(pRsnie_cipher
->ucount
);
472 ========================================================================
475 Build AKM suite in RSN-IE.
476 It only shall be called by RTMPMakeRSNIE.
479 pAd - pointer to our pAdapter context
480 ElementID - indicate the WPA1 or WPA2
481 AuthMode - indicate the authentication mode
482 apidx - indicate the interface index
488 ========================================================================
490 static VOID
RTMPInsertRsnIeAKM(
491 IN PRTMP_ADAPTER pAd
,
498 RSNIE_AUTH
*pRsnie_auth
;
500 pRsnie_auth
= (RSNIE_AUTH
*)(pRsnIe
+ (*rsn_len
));
502 // decide WPA2 or WPA1
503 if (ElementID
== Wpa2Ie
)
507 case Ndis802_11AuthModeWPA2
:
508 case Ndis802_11AuthModeWPA1WPA2
:
509 pRsnie_auth
->acount
= 1;
510 NdisMoveMemory(pRsnie_auth
->auth
[0].oui
, OUI_WPA2_8021X_AKM
, 4);
513 case Ndis802_11AuthModeWPA2PSK
:
514 case Ndis802_11AuthModeWPA1PSKWPA2PSK
:
515 pRsnie_auth
->acount
= 1;
516 NdisMoveMemory(pRsnie_auth
->auth
[0].oui
, OUI_WPA2_PSK_AKM
, 4);
524 case Ndis802_11AuthModeWPA
:
525 case Ndis802_11AuthModeWPA1WPA2
:
526 pRsnie_auth
->acount
= 1;
527 NdisMoveMemory(pRsnie_auth
->auth
[0].oui
, OUI_WPA_8021X_AKM
, 4);
530 case Ndis802_11AuthModeWPAPSK
:
531 case Ndis802_11AuthModeWPA1PSKWPA2PSK
:
532 pRsnie_auth
->acount
= 1;
533 NdisMoveMemory(pRsnie_auth
->auth
[0].oui
, OUI_WPA_PSK_AKM
, 4);
536 case Ndis802_11AuthModeWPANone
:
537 pRsnie_auth
->acount
= 1;
538 NdisMoveMemory(pRsnie_auth
->auth
[0].oui
, OUI_WPA_NONE_AKM
, 4);
543 pRsnie_auth
->acount
= cpu2le16(pRsnie_auth
->acount
);
545 (*rsn_len
) += sizeof(RSNIE_AUTH
); // update current RSNIE length
550 ========================================================================
553 Build capability in RSN-IE.
554 It only shall be called by RTMPMakeRSNIE.
557 pAd - pointer to our pAdapter context
558 ElementID - indicate the WPA1 or WPA2
559 apidx - indicate the interface index
565 ========================================================================
567 static VOID
RTMPInsertRsnIeCap(
568 IN PRTMP_ADAPTER pAd
,
574 RSN_CAPABILITIES
*pRSN_Cap
;
576 // it could be ignored in WPA1 mode
577 if (ElementID
== WpaIe
)
580 pRSN_Cap
= (RSN_CAPABILITIES
*)(pRsnIe
+ (*rsn_len
));
583 pRSN_Cap
->word
= cpu2le16(pRSN_Cap
->word
);
585 (*rsn_len
) += sizeof(RSN_CAPABILITIES
); // update current RSNIE length
591 ========================================================================
594 Build RSN IE context. It is not included element-ID and length.
597 pAd - pointer to our pAdapter context
598 AuthMode - indicate the authentication mode
599 WepStatus - indicate the encryption type
600 apidx - indicate the interface index
606 ========================================================================
609 IN PRTMP_ADAPTER pAd
,
614 PUCHAR pRsnIe
= NULL
; // primary RSNIE
615 UCHAR
*rsnielen_cur_p
= 0; // the length of the primary RSNIE
616 UCHAR
*rsnielen_ex_cur_p
= 0; // the length of the secondary RSNIE
618 BOOLEAN bMixCipher
= FALSE
; // indicate the pairwise and group cipher are different
620 WPA_MIX_PAIR_CIPHER FlexibleCipher
= WPA_TKIPAES_WPA2_TKIPAES
; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
622 rsnielen_cur_p
= NULL
;
623 rsnielen_ex_cur_p
= NULL
;
627 if (pAd
->StaCfg
.WpaSupplicantUP
!= WPA_SUPPLICANT_DISABLE
)
629 if (AuthMode
< Ndis802_11AuthModeWPA
)
634 // Support WPAPSK or WPA2PSK in STA-Infra mode
635 // Support WPANone in STA-Adhoc mode
636 if ((AuthMode
!= Ndis802_11AuthModeWPAPSK
) &&
637 (AuthMode
!= Ndis802_11AuthModeWPA2PSK
) &&
638 (AuthMode
!= Ndis802_11AuthModeWPANone
)
643 DBGPRINT(RT_DEBUG_TRACE
,("==> RTMPMakeRSNIE(STA)\n"));
645 // Zero RSNIE context
646 pAd
->StaCfg
.RSNIE_Len
= 0;
647 NdisZeroMemory(pAd
->StaCfg
.RSN_IE
, MAX_LEN_OF_RSNIE
);
650 rsnielen_cur_p
= &pAd
->StaCfg
.RSNIE_Len
;
651 pRsnIe
= pAd
->StaCfg
.RSN_IE
;
653 bMixCipher
= pAd
->StaCfg
.bMixCipher
;
657 // indicate primary RSNIE as WPA or WPA2
658 if ((AuthMode
== Ndis802_11AuthModeWPA
) ||
659 (AuthMode
== Ndis802_11AuthModeWPAPSK
) ||
660 (AuthMode
== Ndis802_11AuthModeWPANone
) ||
661 (AuthMode
== Ndis802_11AuthModeWPA1WPA2
) ||
662 (AuthMode
== Ndis802_11AuthModeWPA1PSKWPA2PSK
))
663 PrimaryRsnie
= WpaIe
;
665 PrimaryRsnie
= Wpa2Ie
;
668 // Build the primary RSNIE
669 // 1. insert cipher suite
670 RTMPInsertRsnIeCipher(pAd
, PrimaryRsnie
, WepStatus
, bMixCipher
, FlexibleCipher
, pRsnIe
, &p_offset
);
673 RTMPInsertRsnIeAKM(pAd
, PrimaryRsnie
, AuthMode
, apidx
, pRsnIe
, &p_offset
);
675 // 3. insert capability
676 RTMPInsertRsnIeCap(pAd
, PrimaryRsnie
, apidx
, pRsnIe
, &p_offset
);
679 // 4. update the RSNIE length
680 *rsnielen_cur_p
= p_offset
;
682 hex_dump("The primary RSNIE", pRsnIe
, (*rsnielen_cur_p
));
688 ==========================================================================
690 Check whether the received frame is EAP frame.
693 pAd - pointer to our pAdapter context
694 pEntry - pointer to active entry
695 pData - the received frame
696 DataByteCount - the received frame's length
697 FromWhichBSSID - indicate the interface index
700 TRUE - This frame is EAP frame
702 ==========================================================================
704 BOOLEAN
RTMPCheckWPAframe(
705 IN PRTMP_ADAPTER pAd
,
706 IN PMAC_TABLE_ENTRY pEntry
,
708 IN ULONG DataByteCount
,
709 IN UCHAR FromWhichBSSID
)
715 if(DataByteCount
< (LENGTH_802_1_H
+ LENGTH_EAPOL_H
))
720 if (NdisEqualMemory(SNAP_802_1H
, pData
, 6) ||
721 // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
722 NdisEqualMemory(SNAP_BRIDGE_TUNNEL
, pData
, 6))
726 // Skip 2-bytes EAPoL type
727 if (NdisEqualMemory(EAPOL
, pData
, 2))
737 Body_len
= (*(pData
+2)<<8) | (*(pData
+3));
738 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len
));
741 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
742 if (pEntry
->EnqueueEapolStartTimerRunning
!= EAPOL_START_DISABLE
)
744 DBGPRINT(RT_DEBUG_TRACE
, ("Cancel the EnqueueEapolStartTimerRunning \n"));
745 RTMPCancelTimer(&pEntry
->EnqueueStartForPSKTimer
, &Cancelled
);
746 pEntry
->EnqueueEapolStartTimerRunning
= EAPOL_START_DISABLE
;
750 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
753 Body_len
= (*(pData
+2)<<8) | (*(pData
+3));
754 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len
));
757 DBGPRINT(RT_DEBUG_TRACE
, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
767 ========================================================================
770 Misc function to decrypt AES body
777 This function references to RFC 3394 for aes key unwrap algorithm.
779 ========================================================================
781 VOID
AES_GTK_KEY_UNWRAP(
783 OUT UCHAR
*plaintext
,
785 IN UCHAR
*ciphertext
)
788 UCHAR A
[8], BIN
[16], BOUT
[16];
793 INT num_blocks
= c_len
/8; // unit:64bits
796 os_alloc_mem(NULL
, (PUCHAR
*)&R
, 512);
800 DBGPRINT(RT_DEBUG_ERROR
, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
805 NdisMoveMemory(A
, ciphertext
, 8);
807 for(i
= 0; i
< (c_len
-8); i
++)
809 R
[ i
] = ciphertext
[i
+ 8];
812 rtmp_aes_set_key(&aesctx
, key
, 128);
814 for(j
= 5; j
>= 0; j
--)
816 for(i
= (num_blocks
-1); i
> 0; i
--)
818 xor = (num_blocks
-1 )* j
+ i
;
819 NdisMoveMemory(BIN
, A
, 8);
821 NdisMoveMemory(&BIN
[8], &R
[(i
-1)*8], 8);
822 rtmp_aes_decrypt(&aesctx
, BIN
, BOUT
);
823 NdisMoveMemory(A
, &BOUT
[0], 8);
824 NdisMoveMemory(&R
[(i
-1)*8], &BOUT
[8], 8);
829 for(i
= 0; i
< c_len
; i
++)
835 os_free_mem(NULL
, R
);