]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/cmm_wpa.c
staging/trivial: fix typos concerning "initiali[zs]e"
[net-next-2.6.git] / drivers / staging / rt2860 / common / cmm_wpa.c
CommitLineData
91980990
GKH
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 wpa.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
37*/
38#include "../rt_config.h"
ec278fa2 39/* WPA OUI */
51126deb
BZ
40u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 };
41u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 };
42u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 };
43u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 };
44u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 };
45u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 };
46u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 };
47u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 };
96b3c83d 48
ec278fa2 49/* WPA2 OUI */
51126deb
BZ
50u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 };
51u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 };
52u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 };
53u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 };
54u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 };
55u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 };
56
62eb734b 57static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
51126deb
BZ
58 u8 GroupKeyWepStatus,
59 u8 keyDescVer,
60 u8 MsgType,
61 u8 DefaultKeyIdx,
62 u8 * GTK,
63 u8 * RSNIE,
62eb734b 64 u8 RSNIE_LEN, struct rt_eapol_packet * pMsg);
51126deb
BZ
65
66static void CalculateMIC(u8 KeyDescVer,
62eb734b 67 u8 * PTK, struct rt_eapol_packet * pMsg);
51126deb 68
62eb734b 69static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
51126deb 70
62eb734b
BZ
71static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd,
72 struct rt_mlme_queue_elem *Elem);
96b3c83d 73
62eb734b
BZ
74static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd,
75 struct rt_mlme_queue_elem *Elem);
96b3c83d 76
62eb734b
BZ
77static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd,
78 struct rt_mlme_queue_elem *Elem);
96b3c83d 79
62eb734b 80static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
91980990
GKH
81
82/*
ca97b838
BZ
83 ==========================================================================
84 Description:
85 association state machine init, including state transition and timer init
86 Parameters:
87 S - pointer to the association state machine
88 ==========================================================================
89 */
62eb734b
BZ
90void WpaStateMachineInit(struct rt_rtmp_adapter *pAd,
91 struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[])
ca97b838 92{
96b3c83d
BZ
93 StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE,
94 MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK,
95 WPA_MACHINE_BASE);
96
97 StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket,
98 (STATE_MACHINE_FUNC) WpaEAPPacketAction);
99 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart,
100 (STATE_MACHINE_FUNC) WpaEAPOLStartAction);
101 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff,
102 (STATE_MACHINE_FUNC) WpaEAPOLLogoffAction);
103 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey,
104 (STATE_MACHINE_FUNC) WpaEAPOLKeyAction);
105 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert,
106 (STATE_MACHINE_FUNC) WpaEAPOLASFAlertAction);
ca97b838 107}
91980990 108
ca97b838
BZ
109/*
110 ==========================================================================
111 Description:
112 this is state machine function.
113 When receiving EAP packets which is for 802.1x authentication use.
114 Not use in PSK case
115 Return:
116 ==========================================================================
117*/
62eb734b 118void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
ca97b838
BZ
119{
120}
121
62eb734b 122void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
ca97b838
BZ
123{
124}
125
62eb734b 126void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
ca97b838
BZ
127{
128}
129
130/*
131 ==========================================================================
132 Description:
133 Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
134 Return:
135 ==========================================================================
136*/
62eb734b 137void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
ca97b838 138{
62eb734b
BZ
139 struct rt_mac_table_entry *pEntry;
140 struct rt_header_802_11 * pHeader;
96b3c83d
BZ
141
142 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
143
62eb734b 144 pHeader = (struct rt_header_802_11 *) Elem->Msg;
96b3c83d 145
ec278fa2 146 /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */
96b3c83d
BZ
147 if (Elem->MsgLen == 6)
148 pEntry = MacTableLookup(pAd, Elem->Msg);
149 else {
150 pEntry = MacTableLookup(pAd, pHeader->Addr2);
151 }
152
153 if (pEntry) {
154 DBGPRINT(RT_DEBUG_TRACE,
155 (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n",
156 pEntry->PortSecured, pEntry->WpaState,
157 pEntry->AuthMode, pEntry->PMKID_CacheIdx));
158
159 if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
160 && (pEntry->WpaState < AS_PTKSTART)
161 && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
162 || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
163 || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
164 && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) {
165 pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
166 pEntry->WpaState = AS_INITPSK;
167 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
168 NdisZeroMemory(pEntry->R_Counter,
169 sizeof(pEntry->R_Counter));
170 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
171
172 WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
173 }
174 }
ca97b838
BZ
175}
176
177/*
178 ==========================================================================
179 Description:
180 This is state machine function.
181 When receiving EAPOL packets which is for 802.1x key management.
182 Use both in WPA, and WPAPSK case.
183 In this function, further dispatch to different functions according to the received packet. 3 categories are :
184 1. normal 4-way pairwisekey and 2-way groupkey handshake
185 2. MIC error (Countermeasures attack) report packet from STA.
186 3. Request for pairwise/group key update from STA
187 Return:
188 ==========================================================================
189*/
62eb734b 190void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
ca97b838 191{
62eb734b
BZ
192 struct rt_mac_table_entry *pEntry;
193 struct rt_header_802_11 * pHeader;
194 struct rt_eapol_packet * pEapol_packet;
195 struct rt_key_info peerKeyInfo;
ca97b838 196
96b3c83d 197 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
ca97b838 198
62eb734b 199 pHeader = (struct rt_header_802_11 *) Elem->Msg;
96b3c83d 200 pEapol_packet =
62eb734b 201 (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
ca97b838 202
51126deb
BZ
203 NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo));
204 NdisMoveMemory((u8 *)& peerKeyInfo,
205 (u8 *)& pEapol_packet->KeyDesc.KeyInfo,
62eb734b 206 sizeof(struct rt_key_info));
ca97b838 207
96b3c83d
BZ
208 hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet,
209 (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
ca97b838 210
51126deb 211 *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo));
ca97b838 212
96b3c83d
BZ
213 do {
214 pEntry = MacTableLookup(pAd, pHeader->Addr2);
ca97b838 215
96b3c83d
BZ
216 if (!pEntry
217 || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
218 break;
ca97b838
BZ
219
220 if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
96b3c83d 221 break;
ca97b838 222
96b3c83d
BZ
223 DBGPRINT(RT_DEBUG_TRACE,
224 ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n",
225 PRINT_MAC(pEntry->Addr)));
ca97b838 226
96b3c83d
BZ
227 if (((pEapol_packet->ProVer != EAPOL_VER)
228 && (pEapol_packet->ProVer != EAPOL_VER2))
229 || ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC)
230 && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) {
231 DBGPRINT(RT_DEBUG_ERROR,
232 ("Key descripter does not match with WPA rule\n"));
233 break;
234 }
ec278fa2
BZ
235 /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */
236 /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */
96b3c83d
BZ
237 if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled)
238 && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) {
239 DBGPRINT(RT_DEBUG_ERROR,
240 ("Key descripter version not match(TKIP) \n"));
241 break;
242 }
ec278fa2
BZ
243 /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */
244 /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */
96b3c83d
BZ
245 else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
246 && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) {
247 DBGPRINT(RT_DEBUG_ERROR,
248 ("Key descripter version not match(AES) \n"));
249 break;
250 }
ec278fa2 251 /* Check if this STA is in class 3 state and the WPA state is started */
96b3c83d
BZ
252 if ((pEntry->Sst == SST_ASSOC)
253 && (pEntry->WpaState >= AS_INITPSK)) {
ec278fa2
BZ
254 /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */
255 /* or not. */
256 /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */
257 /* Key frame from the Authenticator must not have the Ack bit set. */
96b3c83d 258 if (peerKeyInfo.KeyAck == 1) {
ec278fa2
BZ
259 /* The frame is snet by Authenticator. */
260 /* So the Supplicant side shall handle this. */
ca97b838 261
96b3c83d
BZ
262 if ((peerKeyInfo.Secure == 0)
263 && (peerKeyInfo.Request == 0)
264 && (peerKeyInfo.Error == 0)
265 && (peerKeyInfo.KeyType == PAIRWISEKEY)) {
ec278fa2
BZ
266 /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */
267 /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
268 /* 2. the message 3 of 4-way HS in WPA */
269 /* EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
ca97b838 270 if (peerKeyInfo.KeyMic == 0)
96b3c83d
BZ
271 PeerPairMsg1Action(pAd, pEntry,
272 Elem);
273 else
274 PeerPairMsg3Action(pAd, pEntry,
275 Elem);
276 } else if ((peerKeyInfo.Secure == 1)
277 && (peerKeyInfo.KeyMic == 1)
278 && (peerKeyInfo.Request == 0)
279 && (peerKeyInfo.Error == 0)) {
ec278fa2
BZ
280 /* Process 1. the message 3 of 4-way HS in WPA2 */
281 /* EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
282 /* 2. the message 1 of group KS in WPA or WPA2 */
283 /* EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */
ca97b838 284 if (peerKeyInfo.KeyType == PAIRWISEKEY)
96b3c83d
BZ
285 PeerPairMsg3Action(pAd, pEntry,
286 Elem);
ca97b838 287 else
96b3c83d
BZ
288 PeerGroupMsg1Action(pAd, pEntry,
289 Elem);
ca97b838 290 }
96b3c83d 291 } else {
ec278fa2
BZ
292 /* The frame is snet by Supplicant. */
293 /* So the Authenticator side shall handle this. */
ca97b838 294 if ((peerKeyInfo.Request == 0) &&
96b3c83d
BZ
295 (peerKeyInfo.Error == 0) &&
296 (peerKeyInfo.KeyMic == 1)) {
297 if (peerKeyInfo.Secure == 0
298 && peerKeyInfo.KeyType ==
299 PAIRWISEKEY) {
ec278fa2
BZ
300 /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */
301 /* Process 1. message 2 of 4-way HS in WPA or WPA2 */
302 /* 2. message 4 of 4-way HS in WPA */
51126deb 303 if (CONV_ARRARY_TO_u16
96b3c83d
BZ
304 (pEapol_packet->KeyDesc.
305 KeyDataLen) == 0) {
306 PeerPairMsg4Action(pAd,
307 pEntry,
308 Elem);
309 } else {
310 PeerPairMsg2Action(pAd,
311 pEntry,
312 Elem);
ca97b838 313 }
96b3c83d
BZ
314 } else if (peerKeyInfo.Secure == 1
315 && peerKeyInfo.KeyType ==
316 PAIRWISEKEY) {
ec278fa2
BZ
317 /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */
318 /* Process message 4 of 4-way HS in WPA2 */
96b3c83d
BZ
319 PeerPairMsg4Action(pAd, pEntry,
320 Elem);
321 } else if (peerKeyInfo.Secure == 1
322 && peerKeyInfo.KeyType ==
323 GROUPKEY) {
ec278fa2
BZ
324 /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */
325 /* Process message 2 of Group key HS in WPA or WPA2 */
96b3c83d
BZ
326 PeerGroupMsg2Action(pAd, pEntry,
327 &Elem->
328 Msg
329 [LENGTH_802_11],
330 (Elem->
331 MsgLen -
332 LENGTH_802_11));
ca97b838
BZ
333 }
334 }
335 }
96b3c83d
BZ
336 }
337 } while (FALSE);
ca97b838
BZ
338}
339
340/*
341 ========================================================================
342
343 Routine Description:
344 Copy frame from waiting queue into relative ring buffer and set
345 appropriate ASIC register to kick hardware encryption before really
346 sent out to air.
91980990
GKH
347
348 Arguments:
ca97b838 349 pAd Pointer to our adapter
8a10a546 350 void * Pointer to outgoing Ndis frame
ca97b838 351 NumberOfFrag Number of fragment required
91980990
GKH
352
353 Return Value:
ca97b838 354 None
91980990
GKH
355
356 Note:
91980990
GKH
357
358 ========================================================================
359*/
62eb734b
BZ
360void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd,
361 struct rt_mac_table_entry *pEntry,
51126deb
BZ
362 u8 *pHeader802_3,
363 u32 HdrLen,
364 u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame)
91980990 365{
8a10a546 366 void *pPacket;
51126deb 367 int Status;
91980990 368
ca97b838
BZ
369 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
370 return;
91980990 371
96b3c83d 372 do {
ec278fa2 373 /* build a NDIS packet */
96b3c83d
BZ
374 Status =
375 RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen,
376 pData, DataLen);
ca97b838 377 if (Status != NDIS_STATUS_SUCCESS)
96b3c83d 378 break;
ca97b838 379
96b3c83d
BZ
380 if (bClearFrame)
381 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
382 else
383 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
ca97b838
BZ
384 {
385 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
386
ec278fa2 387 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */
96b3c83d
BZ
388 if (pEntry->apidx != 0)
389 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket,
390 pEntry->
391 apidx);
ca97b838 392
51126deb 393 RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
ca97b838
BZ
394 RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
395 }
396
397 {
ec278fa2 398 /* send out the packet */
96b3c83d
BZ
399 Status = STASendPacket(pAd, pPacket);
400 if (Status == NDIS_STATUS_SUCCESS) {
51126deb 401 u8 Index;
ca97b838 402
ec278fa2
BZ
403 /* Dequeue one frame from TxSwQueue0..3 queue and process it */
404 /* There are three place calling dequeue for TX ring. */
405 /* 1. Here, right after queueing the frame. */
406 /* 2. At the end of TxRingTxDone service routine. */
407 /* 3. Upon NDIS call RTMPSendPackets */
96b3c83d
BZ
408 if ((!RTMP_TEST_FLAG
409 (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
410 &&
411 (!RTMP_TEST_FLAG
412 (pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) {
413 for (Index = 0; Index < 5; Index++)
414 if (pAd->TxSwQueue[Index].
415 Number > 0)
416 RTMPDeQueuePacket(pAd,
417 FALSE,
418 Index,
419 MAX_TX_PROCESS);
ca97b838
BZ
420 }
421 }
422 }
423
96b3c83d 424 } while (FALSE);
ca97b838
BZ
425}
426
427/*
428 ==========================================================================
429 Description:
37523e84 430 This is a function to initialize 4-way handshake
ca97b838
BZ
431
432 Return:
433
434 ==========================================================================
435*/
62eb734b
BZ
436void WPAStart4WayHS(struct rt_rtmp_adapter *pAd,
437 struct rt_mac_table_entry *pEntry, unsigned long TimeInterval)
ca97b838 438{
51126deb 439 u8 Header802_3[14];
62eb734b 440 struct rt_eapol_packet EAPOLPKT;
51126deb
BZ
441 u8 *pBssid = NULL;
442 u8 group_cipher = Ndis802_11WEPDisabled;
ca97b838 443
96b3c83d 444 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
ca97b838 445
96b3c83d
BZ
446 if (RTMP_TEST_FLAG
447 (pAd,
448 fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
ca97b838 449 {
96b3c83d
BZ
450 DBGPRINT(RT_DEBUG_ERROR,
451 ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
ca97b838
BZ
452 return;
453 }
454
96b3c83d
BZ
455 if (pBssid == NULL) {
456 DBGPRINT(RT_DEBUG_ERROR,
457 ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
ca97b838 458 return;
96b3c83d 459 }
ec278fa2 460 /* Check the status */
96b3c83d
BZ
461 if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) {
462 DBGPRINT(RT_DEBUG_ERROR,
463 ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
464 return;
465 }
91980990 466
ec278fa2 467 /* Increment replay counter by 1 */
ca97b838 468 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
91980990 469
ec278fa2 470 /* Randomly generate ANonce */
51126deb 471 GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce);
91980990 472
ec278fa2
BZ
473 /* Construct EAPoL message - Pairwise Msg 1 */
474 /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
62eb734b 475 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
ec278fa2
BZ
476 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_1, 0, /* Default key index */
477 pEntry->ANonce, NULL, /* TxRSC */
478 NULL, /* GTK */
479 NULL, /* RSNIE */
480 0, /* RSNIE length */
96b3c83d 481 &EAPOLPKT);
91980990 482
ec278fa2 483 /* Make outgoing frame */
96b3c83d
BZ
484 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
485 RTMPToWirelessSta(pAd, pEntry, Header802_3,
51126deb
BZ
486 LENGTH_802_3, (u8 *)& EAPOLPKT,
487 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
96b3c83d
BZ
488 (pEntry->PortSecured ==
489 WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
ca97b838 490
ec278fa2 491 /* Trigger Retry Timer */
96b3c83d 492 RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
ca97b838 493
ec278fa2 494 /* Update State */
96b3c83d 495 pEntry->WpaState = AS_PTKSTART;
ca97b838 496
96b3c83d
BZ
497 DBGPRINT(RT_DEBUG_TRACE,
498 ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
ca97b838 499
91980990
GKH
500}
501
502/*
503 ========================================================================
504
505 Routine Description:
ca97b838 506 Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
91980990
GKH
507
508 Arguments:
ca97b838
BZ
509 pAd Pointer to our adapter
510 Elem Message body
91980990
GKH
511
512 Return Value:
ca97b838 513 None
91980990
GKH
514
515 Note:
91980990
GKH
516
517 ========================================================================
518*/
62eb734b
BZ
519void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd,
520 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
91980990 521{
51126deb
BZ
522 u8 PTK[80];
523 u8 Header802_3[14];
62eb734b 524 struct rt_eapol_packet * pMsg1;
51126deb 525 u32 MsgLen;
62eb734b 526 struct rt_eapol_packet EAPOLPKT;
51126deb
BZ
527 u8 *pCurrentAddr = NULL;
528 u8 *pmk_ptr = NULL;
529 u8 group_cipher = Ndis802_11WEPDisabled;
530 u8 *rsnie_ptr = NULL;
531 u8 rsnie_len = 0;
ca97b838
BZ
532
533 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
534
535 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
536 return;
91980990 537
96b3c83d
BZ
538 if (Elem->MsgLen <
539 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
62eb734b 540 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
96b3c83d 541 return;
91980990 542
ca97b838
BZ
543 {
544 pCurrentAddr = pAd->CurrentAddress;
545 pmk_ptr = pAd->StaCfg.PMK;
546 group_cipher = pAd->StaCfg.GroupCipher;
547 rsnie_ptr = pAd->StaCfg.RSN_IE;
548 rsnie_len = pAd->StaCfg.RSNIE_Len;
549 }
91980990 550
ec278fa2 551 /* Store the received frame */
62eb734b 552 pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
ca97b838 553 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
91980990 554
ec278fa2 555 /* Sanity Check peer Pairwise message 1 - Replay Counter */
96b3c83d
BZ
556 if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry)
557 == FALSE)
ca97b838 558 return;
91980990 559
ec278fa2 560 /* Store Replay counter, it will use to verify message 3 and construct message 2 */
96b3c83d
BZ
561 NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter,
562 LEN_KEY_DESC_REPLAY);
ca97b838 563
ec278fa2 564 /* Store ANonce */
96b3c83d
BZ
565 NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce,
566 LEN_KEY_DESC_NONCE);
ca97b838 567
ec278fa2 568 /* Generate random SNonce */
51126deb 569 GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce);
ca97b838
BZ
570
571 {
ec278fa2 572 /* Calculate PTK(ANonce, SNonce) */
96b3c83d
BZ
573 WpaDerivePTK(pAd,
574 pmk_ptr,
575 pEntry->ANonce,
576 pEntry->Addr,
577 pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK);
ca97b838 578
ec278fa2 579 /* Save key to PTK entry */
ca97b838
BZ
580 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
581 }
582
ec278fa2 583 /* Update WpaState */
ca97b838
BZ
584 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
585
ec278fa2
BZ
586 /* Construct EAPoL message - Pairwise Msg 2 */
587 /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */
62eb734b 588 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
ec278fa2
BZ
589 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */
590 pEntry->SNonce, NULL, /* TxRsc */
591 NULL, /* GTK */
51126deb 592 (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
ca97b838 593
ec278fa2 594 /* Make outgoing frame */
ca97b838
BZ
595 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
596
597 RTMPToWirelessSta(pAd, pEntry,
51126deb
BZ
598 Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT,
599 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
ca97b838 600
96b3c83d
BZ
601 DBGPRINT(RT_DEBUG_TRACE,
602 ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
ca97b838
BZ
603}
604
ca97b838
BZ
605/*
606 ==========================================================================
607 Description:
608 When receiving the second packet of 4-way pairwisekey handshake.
609 Return:
610 ==========================================================================
611*/
62eb734b
BZ
612void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd,
613 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
ca97b838 614{
51126deb 615 u8 PTK[80];
96b3c83d 616 BOOLEAN Cancelled;
62eb734b
BZ
617 struct rt_header_802_11 * pHeader;
618 struct rt_eapol_packet EAPOLPKT;
619 struct rt_eapol_packet * pMsg2;
51126deb
BZ
620 u32 MsgLen;
621 u8 Header802_3[LENGTH_802_3];
622 u8 TxTsc[6];
623 u8 *pBssid = NULL;
624 u8 *pmk_ptr = NULL;
625 u8 *gtk_ptr = NULL;
626 u8 default_key = 0;
627 u8 group_cipher = Ndis802_11WEPDisabled;
628 u8 *rsnie_ptr = NULL;
629 u8 rsnie_len = 0;
96b3c83d
BZ
630
631 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
632
633 if ((!pEntry) || (!pEntry->ValidAsCLI))
634 return;
ca97b838 635
96b3c83d
BZ
636 if (Elem->MsgLen <
637 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
62eb734b 638 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
96b3c83d 639 return;
ca97b838 640
ec278fa2 641 /* check Entry in valid State */
96b3c83d
BZ
642 if (pEntry->WpaState < AS_PTKSTART)
643 return;
ca97b838 644
ec278fa2 645 /* pointer to 802.11 header */
62eb734b 646 pHeader = (struct rt_header_802_11 *) Elem->Msg;
ca97b838 647
ec278fa2 648 /* skip 802.11_header(24-byte) and LLC_header(8) */
62eb734b 649 pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
ca97b838
BZ
650 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
651
ec278fa2 652 /* Store SNonce */
96b3c83d
BZ
653 NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce,
654 LEN_KEY_DESC_NONCE);
ca97b838
BZ
655
656 {
ec278fa2 657 /* Derive PTK */
51126deb
BZ
658 WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */
659 (u8 *) pBssid, pEntry->SNonce, /* SNONCE */
96b3c83d
BZ
660 pEntry->Addr, PTK, LEN_PTK);
661
662 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
ca97b838
BZ
663 }
664
ec278fa2 665 /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */
96b3c83d
BZ
666 if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry)
667 == FALSE)
ca97b838
BZ
668 return;
669
96b3c83d 670 do {
ec278fa2 671 /* delete retry timer */
ca97b838
BZ
672 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
673
ec278fa2 674 /* Change state */
96b3c83d 675 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
ca97b838 676
ec278fa2 677 /* Increment replay counter by 1 */
ca97b838
BZ
678 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
679
ec278fa2 680 /* Construct EAPoL message - Pairwise Msg 3 */
62eb734b 681 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
ca97b838 682 ConstructEapolMsg(pEntry,
96b3c83d
BZ
683 group_cipher,
684 EAPOL_PAIR_MSG_3,
685 default_key,
686 pEntry->ANonce,
687 TxTsc,
51126deb
BZ
688 (u8 *) gtk_ptr,
689 (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
96b3c83d 690
ec278fa2 691 /* Make outgoing frame */
96b3c83d
BZ
692 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
693 RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
51126deb
BZ
694 (u8 *)& EAPOLPKT,
695 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
96b3c83d
BZ
696 (pEntry->PortSecured ==
697 WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
698
699 pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
ca97b838
BZ
700 RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
701
ec278fa2 702 /* Update State */
96b3c83d
BZ
703 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
704 } while (FALSE);
ca97b838 705
96b3c83d
BZ
706 DBGPRINT(RT_DEBUG_TRACE,
707 ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
ca97b838
BZ
708}
709
710/*
711 ========================================================================
712
713 Routine Description:
714 Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
715
716 Arguments:
717 pAd Pointer to our adapter
718 Elem Message body
719
720 Return Value:
721 None
722
723 Note:
724
725 ========================================================================
726*/
62eb734b
BZ
727void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd,
728 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
ca97b838 729{
62eb734b 730 struct rt_header_802_11 * pHeader;
51126deb 731 u8 Header802_3[14];
62eb734b
BZ
732 struct rt_eapol_packet EAPOLPKT;
733 struct rt_eapol_packet * pMsg3;
51126deb
BZ
734 u32 MsgLen;
735 u8 *pCurrentAddr = NULL;
736 u8 group_cipher = Ndis802_11WEPDisabled;
ca97b838
BZ
737
738 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
739
740 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
741 return;
742
96b3c83d
BZ
743 if (Elem->MsgLen <
744 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
62eb734b 745 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
ca97b838
BZ
746 return;
747
748 {
749 pCurrentAddr = pAd->CurrentAddress;
750 group_cipher = pAd->StaCfg.GroupCipher;
751
752 }
753
ec278fa2 754 /* Record 802.11 header & the received EAPOL packet Msg3 */
62eb734b
BZ
755 pHeader = (struct rt_header_802_11 *) Elem->Msg;
756 pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
ca97b838
BZ
757 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
758
ec278fa2 759 /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */
96b3c83d
BZ
760 if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry)
761 == FALSE)
ca97b838
BZ
762 return;
763
ec278fa2 764 /* Save Replay counter, it will use construct message 4 */
96b3c83d
BZ
765 NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter,
766 LEN_KEY_DESC_REPLAY);
ca97b838 767
ec278fa2 768 /* Double check ANonce */
96b3c83d
BZ
769 if (!NdisEqualMemory
770 (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) {
ca97b838
BZ
771 return;
772 }
ec278fa2 773 /* Construct EAPoL message - Pairwise Msg 4 */
62eb734b 774 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
ec278fa2
BZ
775 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_4, 0, /* group key index not used in message 4 */
776 NULL, /* Nonce not used in message 4 */
777 NULL, /* TxRSC not used in message 4 */
778 NULL, /* GTK not used in message 4 */
779 NULL, /* RSN IE not used in message 4 */
96b3c83d 780 0, &EAPOLPKT);
ca97b838 781
ec278fa2 782 /* Update WpaState */
ca97b838
BZ
783 pEntry->WpaState = AS_PTKINITDONE;
784
ec278fa2 785 /* Update pairwise key */
ca97b838 786 {
62eb734b 787 struct rt_cipher_key *pSharedKey;
ca97b838
BZ
788
789 pSharedKey = &pAd->SharedKey[BSS0][0];
790
791 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
792
ec278fa2 793 /* Prepare pair-wise key information into shared key table */
62eb734b 794 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
ca97b838 795 pSharedKey->KeyLen = LEN_TKIP_EK;
96b3c83d
BZ
796 NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32],
797 LEN_TKIP_EK);
798 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
799 LEN_TKIP_RXMICK);
800 NdisMoveMemory(pSharedKey->TxMic,
801 &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
802 LEN_TKIP_TXMICK);
ca97b838 803
ec278fa2 804 /* Decide its ChiperAlg */
ca97b838
BZ
805 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
806 pSharedKey->CipherAlg = CIPHER_TKIP;
807 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
808 pSharedKey->CipherAlg = CIPHER_AES;
809 else
810 pSharedKey->CipherAlg = CIPHER_NONE;
811
62eb734b 812 /* Update these related information to struct rt_mac_table_entry */
ca97b838 813 pEntry = &pAd->MacTab.Content[BSSID_WCID];
96b3c83d
BZ
814 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
815 LEN_TKIP_EK);
816 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
817 LEN_TKIP_RXMICK);
818 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
819 &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
820 LEN_TKIP_TXMICK);
ca97b838
BZ
821 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
822
ec278fa2 823 /* Update pairwise key information to ASIC Shared Key Table */
ca97b838 824 AsicAddSharedKeyEntry(pAd,
96b3c83d
BZ
825 BSS0,
826 0,
827 pSharedKey->CipherAlg,
828 pSharedKey->Key,
829 pSharedKey->TxMic, pSharedKey->RxMic);
ca97b838 830
ec278fa2 831 /* Update ASIC WCID attribute table and IVEIV table */
ca97b838 832 RTMPAddWcidAttributeEntry(pAd,
96b3c83d
BZ
833 BSS0,
834 0, pSharedKey->CipherAlg, pEntry);
ca97b838
BZ
835
836 }
837
ec278fa2 838 /* open 802.1x port control and privacy filter */
ca97b838 839 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
96b3c83d 840 pEntry->AuthMode == Ndis802_11AuthModeWPA2) {
ca97b838
BZ
841 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
842 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
843
844 STA_PORT_SECURED(pAd);
ec278fa2 845 /* Indicate Connected for GUI */
96b3c83d
BZ
846 pAd->IndicateMediaState = NdisMediaStateConnected;
847 DBGPRINT(RT_DEBUG_TRACE,
848 ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
849 GetAuthMode(pEntry->AuthMode),
850 GetEncryptType(pEntry->WepStatus),
851 GetEncryptType(group_cipher)));
852 } else {
ca97b838
BZ
853 }
854
ec278fa2 855 /* Init 802.3 header and send out */
ca97b838
BZ
856 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
857 RTMPToWirelessSta(pAd, pEntry,
96b3c83d 858 Header802_3, sizeof(Header802_3),
51126deb
BZ
859 (u8 *)& EAPOLPKT,
860 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
ca97b838 861
96b3c83d
BZ
862 DBGPRINT(RT_DEBUG_TRACE,
863 ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
ca97b838
BZ
864}
865
866/*
867 ==========================================================================
868 Description:
869 When receiving the last packet of 4-way pairwisekey handshake.
37523e84 870 Initialize 2-way groupkey handshake following.
ca97b838
BZ
871 Return:
872 ==========================================================================
873*/
62eb734b
BZ
874void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd,
875 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
ca97b838 876{
62eb734b
BZ
877 struct rt_eapol_packet * pMsg4;
878 struct rt_header_802_11 * pHeader;
51126deb 879 u32 MsgLen;
96b3c83d 880 BOOLEAN Cancelled;
51126deb 881 u8 group_cipher = Ndis802_11WEPDisabled;
ca97b838 882
96b3c83d 883 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
ca97b838 884
96b3c83d
BZ
885 do {
886 if ((!pEntry) || (!pEntry->ValidAsCLI))
887 break;
ca97b838 888
96b3c83d
BZ
889 if (Elem->MsgLen <
890 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
62eb734b 891 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
96b3c83d 892 break;
ca97b838 893
96b3c83d
BZ
894 if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
895 break;
ca97b838 896
ec278fa2 897 /* pointer to 802.11 header */
62eb734b 898 pHeader = (struct rt_header_802_11 *) Elem->Msg;
ca97b838 899
ec278fa2 900 /* skip 802.11_header(24-byte) and LLC_header(8) */
96b3c83d 901 pMsg4 =
62eb734b 902 (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
ca97b838
BZ
903 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
904
ec278fa2 905 /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */
96b3c83d
BZ
906 if (PeerWpaMessageSanity
907 (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
ca97b838
BZ
908 break;
909
ec278fa2 910 /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */
62eb734b 911 NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key));
ca97b838 912
ec278fa2 913 /* reset IVEIV in Asic */
ca97b838
BZ
914 AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
915
96b3c83d
BZ
916 pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK;
917 NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32],
918 LEN_TKIP_EK);
919 NdisMoveMemory(pEntry->PairwiseKey.RxMic,
920 &pEntry->PTK[TKIP_AP_RXMICK_OFFSET],
921 LEN_TKIP_RXMICK);
922 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
923 &pEntry->PTK[TKIP_AP_TXMICK_OFFSET],
924 LEN_TKIP_TXMICK);
ca97b838 925
ec278fa2 926 /* Set pairwise key to Asic */
96b3c83d
BZ
927 {
928 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
929 if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
930 pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
931 else if (pEntry->WepStatus ==
932 Ndis802_11Encryption3Enabled)
933 pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
ca97b838 934
ec278fa2 935 /* Add Pair-wise key to Asic */
96b3c83d
BZ
936 AsicAddPairwiseKeyEntry(pAd,
937 pEntry->Addr,
51126deb 938 (u8)pEntry->Aid,
96b3c83d 939 &pEntry->PairwiseKey);
ca97b838 940
ec278fa2 941 /* update WCID attribute table and IVEIV table for this entry */
96b3c83d
BZ
942 RTMPAddWcidAttributeEntry(pAd,
943 pEntry->apidx,
944 0,
945 pEntry->PairwiseKey.CipherAlg,
946 pEntry);
947 }
ca97b838 948
ec278fa2 949 /* 4. upgrade state */
96b3c83d
BZ
950 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
951 pEntry->WpaState = AS_PTKINITDONE;
952 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
ca97b838
BZ
953
954 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
96b3c83d 955 pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) {
ca97b838
BZ
956 pEntry->GTKState = REKEY_ESTABLISHED;
957 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
958
ec278fa2 959 /* send wireless event - for set key done WPA2 */
ca97b838 960 if (pAd->CommonCfg.bWirelessEvent)
96b3c83d
BZ
961 RTMPSendWirelessEvent(pAd,
962 IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
963 pEntry->Addr,
964 pEntry->apidx, 0);
965
966 DBGPRINT(RT_DEBUG_OFF,
967 ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
968 pEntry->AuthMode,
969 GetAuthMode(pEntry->AuthMode),
970 pEntry->WepStatus,
971 GetEncryptType(pEntry->WepStatus),
972 group_cipher, GetEncryptType(group_cipher)));
973 } else {
ec278fa2 974 /* 5. init Group 2-way handshake if necessary. */
96b3c83d
BZ
975 WPAStart2WayGroupHS(pAd, pEntry);
976
977 pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
978 RTMPModTimer(&pEntry->RetryTimer,
979 PEER_MSG3_RETRY_EXEC_INTV);
ca97b838 980 }
96b3c83d 981 } while (FALSE);
ca97b838
BZ
982
983}
984
985/*
986 ==========================================================================
987 Description:
988 This is a function to send the first packet of 2-way groupkey handshake
989 Return:
990
991 ==========================================================================
992*/
62eb734b 993void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
ca97b838 994{
51126deb
BZ
995 u8 Header802_3[14];
996 u8 TxTsc[6];
62eb734b 997 struct rt_eapol_packet EAPOLPKT;
51126deb
BZ
998 u8 group_cipher = Ndis802_11WEPDisabled;
999 u8 default_key = 0;
1000 u8 *gnonce_ptr = NULL;
1001 u8 *gtk_ptr = NULL;
1002 u8 *pBssid = NULL;
ca97b838
BZ
1003
1004 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1005
96b3c83d
BZ
1006 if ((!pEntry) || (!pEntry->ValidAsCLI))
1007 return;
ca97b838 1008
96b3c83d 1009 do {
ec278fa2 1010 /* Increment replay counter by 1 */
ca97b838
BZ
1011 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1012
ec278fa2 1013 /* Construct EAPoL message - Group Msg 1 */
62eb734b 1014 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
ca97b838 1015 ConstructEapolMsg(pEntry,
96b3c83d
BZ
1016 group_cipher,
1017 EAPOL_GROUP_MSG_1,
1018 default_key,
51126deb
BZ
1019 (u8 *) gnonce_ptr,
1020 TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT);
ca97b838 1021
ec278fa2 1022 /* Make outgoing frame */
96b3c83d
BZ
1023 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
1024 RTMPToWirelessSta(pAd, pEntry,
1025 Header802_3, LENGTH_802_3,
51126deb
BZ
1026 (u8 *)& EAPOLPKT,
1027 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
96b3c83d 1028 FALSE);
ca97b838 1029
96b3c83d 1030 } while (FALSE);
ca97b838 1031
96b3c83d
BZ
1032 DBGPRINT(RT_DEBUG_TRACE,
1033 ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
ca97b838 1034
96b3c83d 1035 return;
ca97b838
BZ
1036}
1037
1038/*
1039 ========================================================================
1040
1041 Routine Description:
1042 Process Group key 2-way handshaking
1043
1044 Arguments:
1045 pAd Pointer to our adapter
1046 Elem Message body
1047
1048 Return Value:
1049 None
1050
1051 Note:
1052
1053 ========================================================================
1054*/
62eb734b
BZ
1055void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd,
1056 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
ca97b838 1057{
51126deb 1058 u8 Header802_3[14];
62eb734b
BZ
1059 struct rt_eapol_packet EAPOLPKT;
1060 struct rt_eapol_packet * pGroup;
51126deb 1061 u32 MsgLen;
96b3c83d 1062 BOOLEAN Cancelled;
51126deb
BZ
1063 u8 default_key = 0;
1064 u8 group_cipher = Ndis802_11WEPDisabled;
1065 u8 *pCurrentAddr = NULL;
ca97b838
BZ
1066
1067 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1068
1069 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
96b3c83d 1070 return;
ca97b838
BZ
1071
1072 {
1073 pCurrentAddr = pAd->CurrentAddress;
1074 group_cipher = pAd->StaCfg.GroupCipher;
1075 default_key = pAd->StaCfg.DefaultKeyId;
1076 }
1077
ec278fa2 1078 /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */
62eb734b 1079 pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
ca97b838
BZ
1080 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
1081
ec278fa2 1082 /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */
96b3c83d
BZ
1083 if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry)
1084 == FALSE)
ca97b838
BZ
1085 return;
1086
ec278fa2 1087 /* delete retry timer */
ca97b838
BZ
1088 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1089
ec278fa2 1090 /* Save Replay counter, it will use to construct message 2 */
96b3c83d
BZ
1091 NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter,
1092 LEN_KEY_DESC_REPLAY);
ca97b838 1093
ec278fa2 1094 /* Construct EAPoL message - Group Msg 2 */
62eb734b 1095 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
ec278fa2
BZ
1096 ConstructEapolMsg(pEntry, group_cipher, EAPOL_GROUP_MSG_2, default_key, NULL, /* Nonce not used */
1097 NULL, /* TxRSC not used */
1098 NULL, /* GTK not used */
1099 NULL, /* RSN IE not used */
96b3c83d
BZ
1100 0, &EAPOLPKT);
1101
ec278fa2 1102 /* open 802.1x port control and privacy filter */
ca97b838
BZ
1103 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1104 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1105
1106 STA_PORT_SECURED(pAd);
ec278fa2 1107 /* Indicate Connected for GUI */
96b3c83d 1108 pAd->IndicateMediaState = NdisMediaStateConnected;
ca97b838 1109
96b3c83d
BZ
1110 DBGPRINT(RT_DEBUG_TRACE,
1111 ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
1112 GetAuthMode(pEntry->AuthMode),
1113 GetEncryptType(pEntry->WepStatus),
1114 GetEncryptType(group_cipher)));
ca97b838 1115
ec278fa2 1116 /* init header and Fill Packet and send Msg 2 to authenticator */
ca97b838
BZ
1117 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
1118 RTMPToWirelessSta(pAd, pEntry,
96b3c83d 1119 Header802_3, sizeof(Header802_3),
51126deb
BZ
1120 (u8 *)& EAPOLPKT,
1121 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE);
ca97b838 1122
96b3c83d
BZ
1123 DBGPRINT(RT_DEBUG_TRACE,
1124 ("<=== PeerGroupMsg1Action: sned group message 2\n"));
ca97b838
BZ
1125}
1126
1127/*
1128 ==========================================================================
1129 Description:
1130 When receiving the last packet of 2-way groupkey handshake.
1131 Return:
1132 ==========================================================================
1133*/
62eb734b
BZ
1134void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd,
1135 struct rt_mac_table_entry *pEntry,
51126deb 1136 void * Msg, u32 MsgLen)
ca97b838 1137{
51126deb
BZ
1138 u32 Len;
1139 u8 *pData;
96b3c83d 1140 BOOLEAN Cancelled;
62eb734b 1141 struct rt_eapol_packet * pMsg2;
51126deb 1142 u8 group_cipher = Ndis802_11WEPDisabled;
ca97b838
BZ
1143
1144 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1145
96b3c83d
BZ
1146 do {
1147 if ((!pEntry) || (!pEntry->ValidAsCLI))
1148 break;
ca97b838 1149
96b3c83d 1150 if (MsgLen <
62eb734b 1151 (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) -
96b3c83d
BZ
1152 MAX_LEN_OF_RSNIE - 2))
1153 break;
ca97b838 1154
96b3c83d
BZ
1155 if (pEntry->WpaState != AS_PTKINITDONE)
1156 break;
ca97b838 1157
51126deb 1158 pData = (u8 *)Msg;
62eb734b 1159 pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H);
96b3c83d 1160 Len = MsgLen - LENGTH_802_1_H;
ca97b838 1161
ec278fa2 1162 /* Sanity Check peer group message 2 - Replay Counter, MIC */
96b3c83d
BZ
1163 if (PeerWpaMessageSanity
1164 (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1165 break;
ca97b838 1166
ec278fa2 1167 /* 3. upgrade state */
ca97b838
BZ
1168
1169 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
96b3c83d 1170 pEntry->GTKState = REKEY_ESTABLISHED;
ca97b838 1171
96b3c83d
BZ
1172 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
1173 || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
ec278fa2 1174 /* send wireless event - for set key done WPA2 */
ca97b838 1175 if (pAd->CommonCfg.bWirelessEvent)
96b3c83d
BZ
1176 RTMPSendWirelessEvent(pAd,
1177 IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
1178 pEntry->Addr,
1179 pEntry->apidx, 0);
1180
1181 DBGPRINT(RT_DEBUG_OFF,
1182 ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1183 pEntry->AuthMode,
1184 GetAuthMode(pEntry->AuthMode),
1185 pEntry->WepStatus,
1186 GetEncryptType(pEntry->WepStatus),
1187 group_cipher, GetEncryptType(group_cipher)));
1188 } else {
ec278fa2 1189 /* send wireless event - for set key done WPA */
ca97b838 1190 if (pAd->CommonCfg.bWirelessEvent)
96b3c83d
BZ
1191 RTMPSendWirelessEvent(pAd,
1192 IW_SET_KEY_DONE_WPA1_EVENT_FLAG,
1193 pEntry->Addr,
1194 pEntry->apidx, 0);
1195
1196 DBGPRINT(RT_DEBUG_OFF,
1197 ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1198 pEntry->AuthMode,
1199 GetAuthMode(pEntry->AuthMode),
1200 pEntry->WepStatus,
1201 GetEncryptType(pEntry->WepStatus),
1202 group_cipher, GetEncryptType(group_cipher)));
ca97b838 1203 }
96b3c83d 1204 } while (FALSE);
ca97b838
BZ
1205}
1206
1207/*
1208 ========================================================================
1209
1210 Routine Description:
1211 Classify WPA EAP message type
1212
1213 Arguments:
1214 EAPType Value of EAP message type
1215 MsgType Internal Message definition for MLME state machine
1216
1217 Return Value:
1218 TRUE Found appropriate message type
1219 FALSE No appropriate message type
1220
1221 IRQL = DISPATCH_LEVEL
1222
1223 Note:
1224 All these constants are defined in wpa.h
1225 For supplicant, there is only EAPOL Key message avaliable
1226
1227 ========================================================================
1228*/
51126deb 1229BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType)
ca97b838 1230{
96b3c83d
BZ
1231 switch (EAPType) {
1232 case EAPPacket:
1233 *MsgType = MT2_EAPPacket;
1234 break;
1235 case EAPOLStart:
1236 *MsgType = MT2_EAPOLStart;
1237 break;
1238 case EAPOLLogoff:
1239 *MsgType = MT2_EAPOLLogoff;
1240 break;
1241 case EAPOLKey:
1242 *MsgType = MT2_EAPOLKey;
1243 break;
1244 case EAPOLASFAlert:
1245 *MsgType = MT2_EAPOLASFAlert;
1246 break;
1247 default:
1248 return FALSE;
ca97b838
BZ
1249 }
1250 return TRUE;
1251}
1252
1253/*
1254 ========================================================================
1255
1256 Routine Description:
1257 The pseudo-random function(PRF) that hashes various inputs to
1258 derive a pseudo-random value. To add liveness to the pseudo-random
1259 value, a nonce should be one of the inputs.
1260
1261 It is used to generate PTK, GTK or some specific random value.
1262
1263 Arguments:
51126deb
BZ
1264 u8 *key, - the key material for HMAC_SHA1 use
1265 int key_len - the length of key
1266 u8 *prefix - a prefix label
1267 int prefix_len - the length of the label
1268 u8 *data - a specific data with variable length
1269 int data_len - the length of a specific data
1270 int len - the output lenght
ca97b838
BZ
1271
1272 Return Value:
51126deb 1273 u8 *output - the calculated result
ca97b838
BZ
1274
1275 Note:
1276 802.11i-2004 Annex H.3
1277
1278 ========================================================================
1279*/
51126deb
BZ
1280void PRF(u8 * key,
1281 int key_len,
1282 u8 * prefix,
1283 int prefix_len,
1284 u8 * data, int data_len, u8 * output, int len)
ca97b838 1285{
51126deb
BZ
1286 int i;
1287 u8 *input;
1288 int currentindex = 0;
1289 int total_len;
ca97b838 1290
ec278fa2 1291 /* Allocate memory for input */
51126deb 1292 os_alloc_mem(NULL, (u8 **) & input, 1024);
ca97b838 1293
96b3c83d 1294 if (input == NULL) {
06aea994 1295 DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n"));
96b3c83d
BZ
1296 return;
1297 }
ec278fa2 1298 /* Generate concatenation input */
ca97b838
BZ
1299 NdisMoveMemory(input, prefix, prefix_len);
1300
ec278fa2 1301 /* Concatenate a single octet containing 0 */
96b3c83d 1302 input[prefix_len] = 0;
ca97b838 1303
ec278fa2 1304 /* Concatenate specific data */
ca97b838 1305 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
96b3c83d 1306 total_len = prefix_len + 1 + data_len;
ca97b838 1307
ec278fa2
BZ
1308 /* Concatenate a single octet containing 0 */
1309 /* This octet shall be update later */
ca97b838
BZ
1310 input[total_len] = 0;
1311 total_len++;
1312
ec278fa2
BZ
1313 /* Iterate to calculate the result by hmac-sha-1 */
1314 /* Then concatenate to last result */
96b3c83d
BZ
1315 for (i = 0; i < (len + 19) / 20; i++) {
1316 HMAC_SHA1(key, key_len, input, total_len, &output[currentindex],
1317 SHA1_DIGEST_SIZE);
1318 currentindex += 20;
ca97b838 1319
ec278fa2 1320 /* update the last octet */
ca97b838
BZ
1321 input[total_len - 1]++;
1322 }
96b3c83d 1323 os_free_mem(NULL, input);
ca97b838
BZ
1324}
1325
1326/*
1327* F(P, S, c, i) = U1 xor U2 xor ... Uc
1328* U1 = PRF(P, S || Int(i))
1329* U2 = PRF(P, U1)
1330* Uc = PRF(P, Uc-1)
1331*/
1332
96b3c83d
BZ
1333static void F(char *password, unsigned char *ssid, int ssidlength,
1334 int iterations, int count, unsigned char *output)
ca97b838 1335{
96b3c83d
BZ
1336 unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
1337 int i, j;
1338
1339 /* U1 = PRF(P, S || int(i)) */
1340 memcpy(digest, ssid, ssidlength);
1341 digest[ssidlength] = (unsigned char)((count >> 24) & 0xff);
1342 digest[ssidlength + 1] = (unsigned char)((count >> 16) & 0xff);
1343 digest[ssidlength + 2] = (unsigned char)((count >> 8) & 0xff);
1344 digest[ssidlength + 3] = (unsigned char)(count & 0xff);
ec278fa2 1345 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */
96b3c83d
BZ
1346
1347 /* output = U1 */
1348 memcpy(output, digest1, SHA1_DIGEST_SIZE);
1349
1350 for (i = 1; i < iterations; i++) {
1351 /* Un = PRF(P, Un-1) */
ec278fa2 1352 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */
96b3c83d
BZ
1353 memcpy(digest1, digest, SHA1_DIGEST_SIZE);
1354
1355 /* output = output xor Un */
1356 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
1357 output[j] ^= digest[j];
1358 }
1359 }
ca97b838
BZ
1360}
1361
1362/*
1363* password - ascii string up to 63 characters in length
1364* ssid - octet string up to 32 octets
1365* ssidlength - length of ssid in octets
1366* output must be 40 octets in length and outputs 256 bits of key
1367*/
51126deb 1368int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output)
ca97b838 1369{
96b3c83d
BZ
1370 if ((strlen(password) > 63) || (ssidlength > 32))
1371 return 0;
ca97b838 1372
96b3c83d
BZ
1373 F(password, ssid, ssidlength, 4096, 1, output);
1374 F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1375 return 1;
ca97b838
BZ
1376}
1377
ca97b838
BZ
1378/*
1379 ========================================================================
1380
1381 Routine Description:
1382 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
1383 It shall be called by 4-way handshake processing.
1384
1385 Arguments:
1386 pAd - pointer to our pAdapter context
1387 PMK - pointer to PMK
1388 ANonce - pointer to ANonce
1389 AA - pointer to Authenticator Address
1390 SNonce - pointer to SNonce
1391 SA - pointer to Supplicant Address
1392 len - indicate the length of PTK (octet)
1393
1394 Return Value:
1395 Output pointer to the PTK
1396
1397 Note:
1398 Refer to IEEE 802.11i-2004 8.5.1.2
1399
1400 ========================================================================
1401*/
62eb734b 1402void WpaDerivePTK(struct rt_rtmp_adapter *pAd,
51126deb
BZ
1403 u8 * PMK,
1404 u8 * ANonce,
1405 u8 * AA,
1406 u8 * SNonce,
1407 u8 * SA, u8 * output, u32 len)
ca97b838 1408{
51126deb
BZ
1409 u8 concatenation[76];
1410 u32 CurrPos = 0;
1411 u8 temp[32];
1412 u8 Prefix[] =
96b3c83d
BZ
1413 { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1414 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'
1415 };
ca97b838 1416
ec278fa2 1417 /* initiate the concatenation input */
ca97b838
BZ
1418 NdisZeroMemory(temp, sizeof(temp));
1419 NdisZeroMemory(concatenation, 76);
1420
ec278fa2 1421 /* Get smaller address */
ca97b838
BZ
1422 if (RTMPCompareMemory(SA, AA, 6) == 1)
1423 NdisMoveMemory(concatenation, AA, 6);
1424 else
1425 NdisMoveMemory(concatenation, SA, 6);
1426 CurrPos += 6;
1427
ec278fa2 1428 /* Get larger address */
ca97b838
BZ
1429 if (RTMPCompareMemory(SA, AA, 6) == 1)
1430 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1431 else
1432 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1433
ec278fa2
BZ
1434 /* store the larger mac address for backward compatible of */
1435 /* ralink proprietary STA-key issue */
ca97b838
BZ
1436 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
1437 CurrPos += 6;
1438
ec278fa2 1439 /* Get smaller Nonce */
ca97b838 1440 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
ec278fa2 1441 NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
ca97b838
BZ
1442 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1443 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1444 else
1445 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1446 CurrPos += 32;
1447
ec278fa2 1448 /* Get larger Nonce */
ca97b838 1449 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
ec278fa2 1450 NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
ca97b838
BZ
1451 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1452 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1453 else
1454 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1455 CurrPos += 32;
1456
1457 hex_dump("concatenation=", concatenation, 76);
1458
ec278fa2 1459 /* Use PRF to generate PTK */
ca97b838
BZ
1460 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
1461
1462}
1463
1464/*
1465 ========================================================================
1466
1467 Routine Description:
1468 Generate random number by software.
1469
1470 Arguments:
1471 pAd - pointer to our pAdapter context
1472 macAddr - pointer to local MAC address
1473
1474 Return Value:
1475
1476 Note:
1477 802.1ii-2004 Annex H.5
1478
1479 ========================================================================
1480*/
62eb734b 1481void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random)
ca97b838 1482{
51126deb
BZ
1483 int i, curr;
1484 u8 local[80], KeyCounter[32];
1485 u8 result[80];
1486 unsigned long CurrentTime;
1487 u8 prefix[] =
96b3c83d 1488 { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' };
ca97b838 1489
ec278fa2 1490 /* Zero the related information */
ca97b838
BZ
1491 NdisZeroMemory(result, 80);
1492 NdisZeroMemory(local, 80);
1493 NdisZeroMemory(KeyCounter, 32);
1494
96b3c83d 1495 for (i = 0; i < 32; i++) {
ec278fa2 1496 /* copy the local MAC address */
ca97b838 1497 COPY_MAC_ADDR(local, macAddr);
96b3c83d 1498 curr = MAC_ADDR_LEN;
ca97b838 1499
ec278fa2 1500 /* concatenate the current time */
ca97b838 1501 NdisGetSystemUpTime(&CurrentTime);
96b3c83d
BZ
1502 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1503 curr += sizeof(CurrentTime);
ca97b838 1504
ec278fa2 1505 /* concatenate the last result */
96b3c83d
BZ
1506 NdisMoveMemory(&local[curr], result, 32);
1507 curr += 32;
ca97b838 1508
ec278fa2 1509 /* concatenate a variable */
96b3c83d
BZ
1510 NdisMoveMemory(&local[curr], &i, 2);
1511 curr += 2;
ca97b838 1512
ec278fa2 1513 /* calculate the result */
96b3c83d 1514 PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32);
ca97b838
BZ
1515 }
1516
96b3c83d 1517 NdisMoveMemory(random, result, 32);
ca97b838
BZ
1518}
1519
1520/*
1521 ========================================================================
1522
1523 Routine Description:
1524 Build cipher suite in RSN-IE.
1525 It only shall be called by RTMPMakeRSNIE.
1526
1527 Arguments:
1528 pAd - pointer to our pAdapter context
1529 ElementID - indicate the WPA1 or WPA2
1530 WepStatus - indicate the encryption type
1531 bMixCipher - a boolean to indicate the pairwise cipher and group
1532 cipher are the same or not
1533
1534 Return Value:
1535
1536 Note:
1537
1538 ========================================================================
1539*/
62eb734b 1540static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd,
51126deb
BZ
1541 u8 ElementID,
1542 u32 WepStatus,
96b3c83d 1543 IN BOOLEAN bMixCipher,
51126deb
BZ
1544 u8 FlexibleCipher,
1545 u8 *pRsnIe, u8 * rsn_len)
ca97b838 1546{
51126deb 1547 u8 PairwiseCnt;
ca97b838
BZ
1548
1549 *rsn_len = 0;
1550
ec278fa2 1551 /* decide WPA2 or WPA1 */
96b3c83d 1552 if (ElementID == Wpa2Ie) {
62eb734b 1553 struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe;
ca97b838 1554
ec278fa2 1555 /* Assign the verson as 1 */
ca97b838
BZ
1556 pRsnie_cipher->version = 1;
1557
96b3c83d 1558 switch (WepStatus) {
ec278fa2 1559 /* TKIP mode */
96b3c83d
BZ
1560 case Ndis802_11Encryption2Enabled:
1561 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1562 pRsnie_cipher->ucount = 1;
1563 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1564 OUI_WPA2_TKIP, 4);
62eb734b 1565 *rsn_len = sizeof(struct rt_rsnie2);
96b3c83d 1566 break;
ca97b838 1567
ec278fa2 1568 /* AES mode */
96b3c83d
BZ
1569 case Ndis802_11Encryption3Enabled:
1570 if (bMixCipher)
1571 NdisMoveMemory(pRsnie_cipher->mcast,
1572 OUI_WPA2_TKIP, 4);
1573 else
1574 NdisMoveMemory(pRsnie_cipher->mcast,
1575 OUI_WPA2_CCMP, 4);
1576 pRsnie_cipher->ucount = 1;
1577 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1578 OUI_WPA2_CCMP, 4);
62eb734b 1579 *rsn_len = sizeof(struct rt_rsnie2);
96b3c83d 1580 break;
ca97b838 1581
ec278fa2 1582 /* TKIP-AES mix mode */
96b3c83d
BZ
1583 case Ndis802_11Encryption4Enabled:
1584 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1585
1586 PairwiseCnt = 1;
ec278fa2 1587 /* Insert WPA2 TKIP as the first pairwise cipher */
96b3c83d
BZ
1588 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) {
1589 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1590 OUI_WPA2_TKIP, 4);
ec278fa2 1591 /* Insert WPA2 AES as the secondary pairwise cipher */
96b3c83d
BZ
1592 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) {
1593 NdisMoveMemory(pRsnie_cipher->ucast[0].
1594 oui + 4, OUI_WPA2_CCMP,
1595 4);
1596 PairwiseCnt = 2;
ca97b838 1597 }
96b3c83d 1598 } else {
ec278fa2 1599 /* Insert WPA2 AES as the first pairwise cipher */
96b3c83d
BZ
1600 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1601 OUI_WPA2_CCMP, 4);
1602 }
ca97b838 1603
96b3c83d 1604 pRsnie_cipher->ucount = PairwiseCnt;
62eb734b 1605 *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1));
96b3c83d
BZ
1606 break;
1607 }
ca97b838
BZ
1608
1609 if ((pAd->OpMode == OPMODE_STA) &&
96b3c83d
BZ
1610 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1611 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
51126deb 1612 u32 GroupCipher = pAd->StaCfg.GroupCipher;
96b3c83d
BZ
1613 switch (GroupCipher) {
1614 case Ndis802_11GroupWEP40Enabled:
1615 NdisMoveMemory(pRsnie_cipher->mcast,
1616 OUI_WPA2_WEP40, 4);
1617 break;
1618 case Ndis802_11GroupWEP104Enabled:
1619 NdisMoveMemory(pRsnie_cipher->mcast,
1620 OUI_WPA2_WEP104, 4);
1621 break;
ca97b838
BZ
1622 }
1623 }
ec278fa2 1624 /* swap for big-endian platform */
ca97b838 1625 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
96b3c83d
BZ
1626 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1627 } else {
62eb734b 1628 struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe;
ca97b838 1629
ec278fa2 1630 /* Assign OUI and version */
ca97b838 1631 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
96b3c83d 1632 pRsnie_cipher->version = 1;
ca97b838 1633
96b3c83d 1634 switch (WepStatus) {
ec278fa2 1635 /* TKIP mode */
96b3c83d
BZ
1636 case Ndis802_11Encryption2Enabled:
1637 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1638 pRsnie_cipher->ucount = 1;
1639 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1640 OUI_WPA_TKIP, 4);
62eb734b 1641 *rsn_len = sizeof(struct rt_rsnie);
96b3c83d 1642 break;
ca97b838 1643
ec278fa2 1644 /* AES mode */
96b3c83d
BZ
1645 case Ndis802_11Encryption3Enabled:
1646 if (bMixCipher)
1647 NdisMoveMemory(pRsnie_cipher->mcast,
1648 OUI_WPA_TKIP, 4);
1649 else
1650 NdisMoveMemory(pRsnie_cipher->mcast,
1651 OUI_WPA_CCMP, 4);
1652 pRsnie_cipher->ucount = 1;
1653 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1654 OUI_WPA_CCMP, 4);
62eb734b 1655 *rsn_len = sizeof(struct rt_rsnie);
96b3c83d 1656 break;
ca97b838 1657
ec278fa2 1658 /* TKIP-AES mix mode */
96b3c83d
BZ
1659 case Ndis802_11Encryption4Enabled:
1660 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1661
1662 PairwiseCnt = 1;
ec278fa2 1663 /* Insert WPA TKIP as the first pairwise cipher */
96b3c83d
BZ
1664 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) {
1665 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1666 OUI_WPA_TKIP, 4);
ec278fa2 1667 /* Insert WPA AES as the secondary pairwise cipher */
96b3c83d
BZ
1668 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) {
1669 NdisMoveMemory(pRsnie_cipher->ucast[0].
1670 oui + 4, OUI_WPA_CCMP,
1671 4);
1672 PairwiseCnt = 2;
ca97b838 1673 }
96b3c83d 1674 } else {
ec278fa2 1675 /* Insert WPA AES as the first pairwise cipher */
96b3c83d
BZ
1676 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1677 OUI_WPA_CCMP, 4);
1678 }
ca97b838 1679
96b3c83d 1680 pRsnie_cipher->ucount = PairwiseCnt;
62eb734b 1681 *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1));
96b3c83d
BZ
1682 break;
1683 }
ca97b838
BZ
1684
1685 if ((pAd->OpMode == OPMODE_STA) &&
96b3c83d
BZ
1686 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1687 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
51126deb 1688 u32 GroupCipher = pAd->StaCfg.GroupCipher;
96b3c83d
BZ
1689 switch (GroupCipher) {
1690 case Ndis802_11GroupWEP40Enabled:
1691 NdisMoveMemory(pRsnie_cipher->mcast,
1692 OUI_WPA_WEP40, 4);
1693 break;
1694 case Ndis802_11GroupWEP104Enabled:
1695 NdisMoveMemory(pRsnie_cipher->mcast,
1696 OUI_WPA_WEP104, 4);
1697 break;
ca97b838
BZ
1698 }
1699 }
ec278fa2 1700 /* swap for big-endian platform */
ca97b838 1701 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
96b3c83d 1702 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
ca97b838
BZ
1703 }
1704}
1705
1706/*
1707 ========================================================================
1708
1709 Routine Description:
1710 Build AKM suite in RSN-IE.
1711 It only shall be called by RTMPMakeRSNIE.
1712
1713 Arguments:
1714 pAd - pointer to our pAdapter context
1715 ElementID - indicate the WPA1 or WPA2
1716 AuthMode - indicate the authentication mode
1717 apidx - indicate the interface index
1718
1719 Return Value:
1720
1721 Note:
1722
1723 ========================================================================
1724*/
62eb734b 1725static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd,
51126deb
BZ
1726 u8 ElementID,
1727 u32 AuthMode,
1728 u8 apidx,
1729 u8 *pRsnIe, u8 * rsn_len)
ca97b838 1730{
62eb734b 1731 struct rt_rsnie_auth *pRsnie_auth;
51126deb 1732 u8 AkmCnt = 1; /* default as 1 */
ca97b838 1733
62eb734b 1734 pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len));
ca97b838 1735
ec278fa2 1736 /* decide WPA2 or WPA1 */
96b3c83d 1737 if (ElementID == Wpa2Ie) {
ca97b838 1738
96b3c83d
BZ
1739 switch (AuthMode) {
1740 case Ndis802_11AuthModeWPA2:
1741 case Ndis802_11AuthModeWPA1WPA2:
1742 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1743 OUI_WPA2_8021X_AKM, 4);
1744 break;
ca97b838 1745
96b3c83d
BZ
1746 case Ndis802_11AuthModeWPA2PSK:
1747 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1748 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1749 OUI_WPA2_PSK_AKM, 4);
1750 break;
1751 default:
1752 AkmCnt = 0;
1753 break;
1754
1755 }
1756 } else {
1757 switch (AuthMode) {
1758 case Ndis802_11AuthModeWPA:
1759 case Ndis802_11AuthModeWPA1WPA2:
1760 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1761 OUI_WPA_8021X_AKM, 4);
1762 break;
1763
1764 case Ndis802_11AuthModeWPAPSK:
1765 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1766 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1767 OUI_WPA_PSK_AKM, 4);
1768 break;
1769
1770 case Ndis802_11AuthModeWPANone:
1771 NdisMoveMemory(pRsnie_auth->auth[0].oui,
1772 OUI_WPA_NONE_AKM, 4);
1773 break;
1774 default:
1775 AkmCnt = 0;
1776 break;
1777 }
ca97b838
BZ
1778 }
1779
1780 pRsnie_auth->acount = AkmCnt;
1781 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1782
ec278fa2 1783 /* update current RSNIE length */
62eb734b 1784 (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1)));
ca97b838
BZ
1785
1786}
1787
1788/*
1789 ========================================================================
1790
1791 Routine Description:
1792 Build capability in RSN-IE.
1793 It only shall be called by RTMPMakeRSNIE.
1794
1795 Arguments:
1796 pAd - pointer to our pAdapter context
1797 ElementID - indicate the WPA1 or WPA2
1798 apidx - indicate the interface index
1799
1800 Return Value:
1801
1802 Note:
1803
1804 ========================================================================
1805*/
62eb734b 1806static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd,
51126deb
BZ
1807 u8 ElementID,
1808 u8 apidx,
1809 u8 *pRsnIe, u8 * rsn_len)
ca97b838 1810{
96b3c83d 1811 RSN_CAPABILITIES *pRSN_Cap;
ca97b838 1812
ec278fa2 1813 /* it could be ignored in WPA1 mode */
ca97b838
BZ
1814 if (ElementID == WpaIe)
1815 return;
1816
96b3c83d 1817 pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len));
ca97b838
BZ
1818
1819 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1820
ec278fa2 1821 (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */
ca97b838
BZ
1822
1823}
1824
ca97b838
BZ
1825/*
1826 ========================================================================
1827
1828 Routine Description:
1829 Build RSN IE context. It is not included element-ID and length.
1830
1831 Arguments:
1832 pAd - pointer to our pAdapter context
1833 AuthMode - indicate the authentication mode
1834 WepStatus - indicate the encryption type
1835 apidx - indicate the interface index
1836
1837 Return Value:
1838
1839 Note:
1840
1841 ========================================================================
1842*/
62eb734b 1843void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd,
51126deb 1844 u32 AuthMode, u32 WepStatus, u8 apidx)
ca97b838 1845{
51126deb
BZ
1846 u8 *pRsnIe = NULL; /* primary RSNIE */
1847 u8 *rsnielen_cur_p = 0; /* the length of the primary RSNIE */
1848 u8 *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */
1849 u8 PrimaryRsnie;
ec278fa2 1850 BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */
51126deb 1851 u8 p_offset;
ec278fa2 1852 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */
ca97b838
BZ
1853
1854 rsnielen_cur_p = NULL;
1855 rsnielen_ex_cur_p = NULL;
1856
1857 {
1858 {
96b3c83d
BZ
1859 if (pAd->StaCfg.WpaSupplicantUP !=
1860 WPA_SUPPLICANT_DISABLE) {
ca97b838
BZ
1861 if (AuthMode < Ndis802_11AuthModeWPA)
1862 return;
96b3c83d 1863 } else {
ec278fa2
BZ
1864 /* Support WPAPSK or WPA2PSK in STA-Infra mode */
1865 /* Support WPANone in STA-Adhoc mode */
ca97b838 1866 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
96b3c83d
BZ
1867 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
1868 (AuthMode != Ndis802_11AuthModeWPANone)
1869 )
ca97b838
BZ
1870 return;
1871 }
1872
96b3c83d 1873 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n"));
ca97b838 1874
ec278fa2 1875 /* Zero RSNIE context */
ca97b838
BZ
1876 pAd->StaCfg.RSNIE_Len = 0;
1877 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1878
ec278fa2 1879 /* Pointer to RSNIE */
ca97b838
BZ
1880 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1881 pRsnIe = pAd->StaCfg.RSN_IE;
1882
1883 bMixCipher = pAd->StaCfg.bMixCipher;
1884 }
1885 }
1886
ec278fa2 1887 /* indicate primary RSNIE as WPA or WPA2 */
ca97b838 1888 if ((AuthMode == Ndis802_11AuthModeWPA) ||
96b3c83d
BZ
1889 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
1890 (AuthMode == Ndis802_11AuthModeWPANone) ||
1891 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
1892 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
ca97b838 1893 PrimaryRsnie = WpaIe;
91980990 1894 else
ca97b838 1895 PrimaryRsnie = Wpa2Ie;
91980990 1896
ca97b838 1897 {
ec278fa2
BZ
1898 /* Build the primary RSNIE */
1899 /* 1. insert cipher suite */
96b3c83d
BZ
1900 RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher,
1901 FlexibleCipher, pRsnIe, &p_offset);
ca97b838 1902
ec278fa2 1903 /* 2. insert AKM */
96b3c83d
BZ
1904 RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe,
1905 &p_offset);
ca97b838 1906
ec278fa2 1907 /* 3. insert capability */
ca97b838
BZ
1908 RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
1909 }
1910
ec278fa2 1911 /* 4. update the RSNIE length */
ca97b838
BZ
1912 *rsnielen_cur_p = p_offset;
1913
1914 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1915
ca97b838
BZ
1916}
1917
1918/*
1919 ==========================================================================
1920 Description:
1921 Check whether the received frame is EAP frame.
1922
1923 Arguments:
1924 pAd - pointer to our pAdapter context
1925 pEntry - pointer to active entry
1926 pData - the received frame
1927 DataByteCount - the received frame's length
1928 FromWhichBSSID - indicate the interface index
1929
1930 Return:
1931 TRUE - This frame is EAP frame
1932 FALSE - otherwise
1933 ==========================================================================
1934*/
62eb734b
BZ
1935BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd,
1936 struct rt_mac_table_entry *pEntry,
51126deb
BZ
1937 u8 *pData,
1938 unsigned long DataByteCount, u8 FromWhichBSSID)
ca97b838 1939{
51126deb 1940 unsigned long Body_len;
ca97b838
BZ
1941 BOOLEAN Cancelled;
1942
96b3c83d
BZ
1943 if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
1944 return FALSE;
ca97b838 1945
ec278fa2 1946 /* Skip LLC header */
96b3c83d 1947 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
ec278fa2 1948 /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */
96b3c83d
BZ
1949 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) {
1950 pData += 6;
1951 }
ec278fa2 1952 /* Skip 2-bytes EAPoL type */
96b3c83d
BZ
1953 if (NdisEqualMemory(EAPOL, pData, 2)) {
1954 pData += 2;
1955 } else
1956 return FALSE;
1957
1958 switch (*(pData + 1)) {
1959 case EAPPacket:
1960 Body_len = (*(pData + 2) << 8) | (*(pData + 3));
1961 DBGPRINT(RT_DEBUG_TRACE,
1962 ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n",
1963 Body_len));
1964 break;
1965 case EAPOLStart:
1966 DBGPRINT(RT_DEBUG_TRACE,
1967 ("Receive EAPOL-Start frame, TYPE = 1 \n"));
1968 if (pEntry->EnqueueEapolStartTimerRunning !=
1969 EAPOL_START_DISABLE) {
1970 DBGPRINT(RT_DEBUG_TRACE,
1971 ("Cancel the EnqueueEapolStartTimerRunning \n"));
1972 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer,
1973 &Cancelled);
1974 pEntry->EnqueueEapolStartTimerRunning =
1975 EAPOL_START_DISABLE;
1976 }
1977 break;
1978 case EAPOLLogoff:
1979 DBGPRINT(RT_DEBUG_TRACE,
1980 ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
1981 break;
1982 case EAPOLKey:
1983 Body_len = (*(pData + 2) << 8) | (*(pData + 3));
1984 DBGPRINT(RT_DEBUG_TRACE,
1985 ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n",
1986 Body_len));
1987 break;
1988 case EAPOLASFAlert:
1989 DBGPRINT(RT_DEBUG_TRACE,
1990 ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
1991 break;
1992 default:
1993 return FALSE;
1994
1995 }
1996 return TRUE;
ca97b838
BZ
1997}
1998
1999/*
2000 ==========================================================================
2001 Description:
2002 Report the EAP message type
2003
2004 Arguments:
2005 msg - EAPOL_PAIR_MSG_1
2006 EAPOL_PAIR_MSG_2
2007 EAPOL_PAIR_MSG_3
2008 EAPOL_PAIR_MSG_4
2009 EAPOL_GROUP_MSG_1
2010 EAPOL_GROUP_MSG_2
2011
2012 Return:
2013 message type string
2014
2015 ==========================================================================
2016*/
51126deb 2017char *GetEapolMsgType(char msg)
ca97b838 2018{
96b3c83d
BZ
2019 if (msg == EAPOL_PAIR_MSG_1)
2020 return "Pairwise Message 1";
2021 else if (msg == EAPOL_PAIR_MSG_2)
2022 return "Pairwise Message 2";
2023 else if (msg == EAPOL_PAIR_MSG_3)
2024 return "Pairwise Message 3";
2025 else if (msg == EAPOL_PAIR_MSG_4)
2026 return "Pairwise Message 4";
2027 else if (msg == EAPOL_GROUP_MSG_1)
2028 return "Group Message 1";
2029 else if (msg == EAPOL_GROUP_MSG_2)
2030 return "Group Message 2";
2031 else
2032 return "Invalid Message";
ca97b838
BZ
2033}
2034
ca97b838
BZ
2035/*
2036 ========================================================================
2037
2038 Routine Description:
2039 Check Sanity RSN IE of EAPoL message
2040
2041 Arguments:
2042
2043 Return Value:
2044
ca97b838
BZ
2045 ========================================================================
2046*/
62eb734b 2047BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd,
51126deb
BZ
2048 u8 *pData,
2049 u8 DataLen,
62eb734b 2050 struct rt_mac_table_entry *pEntry, u8 * Offset)
ca97b838 2051{
51126deb
BZ
2052 u8 *pVIE;
2053 u8 len;
62eb734b 2054 struct rt_eid * pEid;
96b3c83d 2055 BOOLEAN result = FALSE;
ca97b838
BZ
2056
2057 pVIE = pData;
96b3c83d 2058 len = DataLen;
ca97b838
BZ
2059 *Offset = 0;
2060
62eb734b
BZ
2061 while (len > sizeof(struct rt_rsnie2)) {
2062 pEid = (struct rt_eid *) pVIE;
ec278fa2 2063 /* WPA RSN IE */
96b3c83d
BZ
2064 if ((pEid->Eid == IE_WPA)
2065 && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) {
2066 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA
2067 || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
2068 &&
2069 (NdisEqualMemory
2070 (pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len))
2071 && (pEntry->RSNIE_Len == (pEid->Len + 2))) {
2072 result = TRUE;
ca97b838
BZ
2073 }
2074
2075 *Offset += (pEid->Len + 2);
2076 }
ec278fa2 2077 /* WPA2 RSN IE */
96b3c83d
BZ
2078 else if ((pEid->Eid == IE_RSN)
2079 && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) {
2080 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2
2081 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
2082 && (pEid->Eid == pEntry->RSN_IE[0])
2083 && ((pEid->Len + 2) >= pEntry->RSNIE_Len)
2084 &&
2085 (NdisEqualMemory
2086 (pEid->Octet, &pEntry->RSN_IE[2],
2087 pEntry->RSNIE_Len - 2))) {
2088
2089 result = TRUE;
ca97b838
BZ
2090 }
2091
2092 *Offset += (pEid->Len + 2);
96b3c83d 2093 } else {
ca97b838
BZ
2094 break;
2095 }
91980990 2096
ca97b838 2097 pVIE += (pEid->Len + 2);
96b3c83d 2098 len -= (pEid->Len + 2);
ca97b838 2099 }
91980990 2100
ca97b838
BZ
2101 return result;
2102
2103}
2104
2105/*
2106 ========================================================================
2107
2108 Routine Description:
2109 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
2110 GTK is encaptulated in KDE format at p.83 802.11i D10
2111
2112 Arguments:
2113
2114 Return Value:
2115
2116 Note:
2117 802.11i D10
2118
2119 ========================================================================
2120*/
62eb734b 2121BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd,
51126deb
BZ
2122 u8 *pKeyData,
2123 u8 KeyDataLen,
2124 u8 GroupKeyIndex,
2125 u8 MsgType,
62eb734b 2126 IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry)
ca97b838 2127{
62eb734b 2128 struct rt_kde_encap * pKDE = NULL;
51126deb
BZ
2129 u8 *pMyKeyData = pKeyData;
2130 u8 KeyDataLength = KeyDataLen;
2131 u8 GTKLEN = 0;
2132 u8 DefaultIdx = 0;
2133 u8 skip_offset;
ca97b838 2134
ec278fa2 2135 /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */
96b3c83d 2136 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) {
ec278fa2 2137 /* Check RSN IE whether it is WPA2/WPA2PSK */
96b3c83d
BZ
2138 if (!RTMPCheckRSNIE
2139 (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) {
ec278fa2 2140 /* send wireless event - for RSN IE different */
ca97b838 2141 if (pAd->CommonCfg.bWirelessEvent)
96b3c83d
BZ
2142 RTMPSendWirelessEvent(pAd,
2143 IW_RSNIE_DIFF_EVENT_FLAG,
2144 pEntry->Addr,
2145 pEntry->apidx, 0);
2146
2147 DBGPRINT(RT_DEBUG_ERROR,
2148 ("RSN_IE Different in msg %d of 4-way handshake!\n",
2149 MsgType));
ca97b838 2150 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
96b3c83d
BZ
2151 hex_dump("Desired RSN_IE ", pEntry->RSN_IE,
2152 pEntry->RSNIE_Len);
ca97b838
BZ
2153
2154 return FALSE;
96b3c83d
BZ
2155 } else {
2156 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) {
ca97b838
BZ
2157 WpaShowAllsuite(pMyKeyData, skip_offset);
2158
ec278fa2 2159 /* skip RSN IE */
ca97b838
BZ
2160 pMyKeyData += skip_offset;
2161 KeyDataLength -= skip_offset;
96b3c83d
BZ
2162 DBGPRINT(RT_DEBUG_TRACE,
2163 ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n",
2164 skip_offset));
2165 } else
ca97b838
BZ
2166 return TRUE;
2167 }
2168 }
91980990 2169
96b3c83d
BZ
2170 DBGPRINT(RT_DEBUG_TRACE,
2171 ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n",
2172 KeyDataLength));
ec278fa2 2173 /*hex_dump("remain data", pMyKeyData, KeyDataLength); */
91980990 2174
ec278fa2 2175 /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */
96b3c83d
BZ
2176 if (bWPA2
2177 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) {
ec278fa2 2178 if (KeyDataLength >= 8) /* KDE format exclude GTK length */
96b3c83d 2179 {
62eb734b 2180 pKDE = (struct rt_kde_encap *) pMyKeyData;
91980990 2181
ca97b838 2182 DefaultIdx = pKDE->GTKEncap.Kid;
91980990 2183
ec278fa2 2184 /* Sanity check - KED length */
96b3c83d
BZ
2185 if (KeyDataLength < (pKDE->Len + 2)) {
2186 DBGPRINT(RT_DEBUG_ERROR,
2187 ("ERROR: The len from KDE is too short \n"));
2188 return FALSE;
2189 }
ec278fa2 2190 /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */
96b3c83d
BZ
2191 GTKLEN = pKDE->Len - 6;
2192 if (GTKLEN < LEN_AES_KEY) {
2193 DBGPRINT(RT_DEBUG_ERROR,
2194 ("ERROR: GTK Key length is too short (%d) \n",
2195 GTKLEN));
2196 return FALSE;
ca97b838 2197 }
91980990 2198
96b3c83d
BZ
2199 } else {
2200 DBGPRINT(RT_DEBUG_ERROR,
2201 ("ERROR: KDE format length is too short \n"));
2202 return FALSE;
2203 }
91980990 2204
96b3c83d
BZ
2205 DBGPRINT(RT_DEBUG_TRACE,
2206 ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n",
2207 DefaultIdx, GTKLEN));
ec278fa2 2208 /* skip it */
ca97b838
BZ
2209 pMyKeyData += 8;
2210 KeyDataLength -= 8;
91980990 2211
96b3c83d 2212 } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) {
ca97b838 2213 DefaultIdx = GroupKeyIndex;
96b3c83d
BZ
2214 DBGPRINT(RT_DEBUG_TRACE,
2215 ("GTK DefaultKeyID=%d \n", DefaultIdx));
ca97b838 2216 }
ec278fa2 2217 /* Sanity check - shared key index must be 1 ~ 3 */
96b3c83d
BZ
2218 if (DefaultIdx < 1 || DefaultIdx > 3) {
2219 DBGPRINT(RT_DEBUG_ERROR,
2220 ("ERROR: GTK Key index(%d) is invalid in %s %s \n",
2221 DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"),
2222 GetEapolMsgType(MsgType)));
2223 return FALSE;
ca97b838 2224 }
91980990 2225
ca97b838 2226 {
62eb734b 2227 struct rt_cipher_key *pSharedKey;
ca97b838 2228
ec278fa2 2229 /* set key material, TxMic and RxMic */
ca97b838
BZ
2230 NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2231 pAd->StaCfg.DefaultKeyId = DefaultIdx;
2232
2233 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
2234
ec278fa2 2235 /* Prepare pair-wise key information into shared key table */
62eb734b 2236 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
ca97b838
BZ
2237 pSharedKey->KeyLen = LEN_TKIP_EK;
2238 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
96b3c83d
BZ
2239 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
2240 LEN_TKIP_RXMICK);
2241 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
2242 LEN_TKIP_TXMICK);
ca97b838 2243
ec278fa2 2244 /* Update Shared Key CipherAlg */
ca97b838
BZ
2245 pSharedKey->CipherAlg = CIPHER_NONE;
2246 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
2247 pSharedKey->CipherAlg = CIPHER_TKIP;
96b3c83d
BZ
2248 else if (pAd->StaCfg.GroupCipher ==
2249 Ndis802_11Encryption3Enabled)
ca97b838
BZ
2250 pSharedKey->CipherAlg = CIPHER_AES;
2251 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
2252 pSharedKey->CipherAlg = CIPHER_WEP64;
96b3c83d
BZ
2253 else if (pAd->StaCfg.GroupCipher ==
2254 Ndis802_11GroupWEP104Enabled)
ca97b838
BZ
2255 pSharedKey->CipherAlg = CIPHER_WEP128;
2256
ec278fa2 2257 /* Update group key information to ASIC Shared Key Table */
ca97b838 2258 AsicAddSharedKeyEntry(pAd,
96b3c83d
BZ
2259 BSS0,
2260 pAd->StaCfg.DefaultKeyId,
2261 pSharedKey->CipherAlg,
2262 pSharedKey->Key,
2263 pSharedKey->TxMic, pSharedKey->RxMic);
ca97b838 2264
ec278fa2 2265 /* Update ASIC WCID attribute table and IVEIV table */
ca97b838 2266 RTMPAddWcidAttributeEntry(pAd,
96b3c83d
BZ
2267 BSS0,
2268 pAd->StaCfg.DefaultKeyId,
2269 pSharedKey->CipherAlg, NULL);
91980990
GKH
2270 }
2271
ca97b838
BZ
2272 return TRUE;
2273
91980990
GKH
2274}
2275
2276/*
2277 ========================================================================
2278
2279 Routine Description:
ca97b838
BZ
2280 Construct EAPoL message for WPA handshaking
2281 Its format is below,
2282
2283 +--------------------+
2284 | Protocol Version | 1 octet
2285 +--------------------+
2286 | Protocol Type | 1 octet
2287 +--------------------+
2288 | Body Length | 2 octets
2289 +--------------------+
2290 | Descriptor Type | 1 octet
2291 +--------------------+
2292 | Key Information | 2 octets
2293 +--------------------+
2294 | Key Length | 1 octet
2295 +--------------------+
2296 | Key Repaly Counter | 8 octets
2297 +--------------------+
2298 | Key Nonce | 32 octets
2299 +--------------------+
2300 | Key IV | 16 octets
2301 +--------------------+
2302 | Key RSC | 8 octets
2303 +--------------------+
2304 | Key ID or Reserved | 8 octets
2305 +--------------------+
2306 | Key MIC | 16 octets
2307 +--------------------+
2308 | Key Data Length | 2 octets
2309 +--------------------+
2310 | Key Data | n octets
2311 +--------------------+
2312
91980990 2313 Arguments:
ca97b838 2314 pAd Pointer to our adapter
91980990
GKH
2315
2316 Return Value:
ca97b838 2317 None
91980990
GKH
2318
2319 Note:
2320
2321 ========================================================================
2322*/
62eb734b 2323void ConstructEapolMsg(struct rt_mac_table_entry *pEntry,
51126deb
BZ
2324 u8 GroupKeyWepStatus,
2325 u8 MsgType,
2326 u8 DefaultKeyIdx,
2327 u8 * KeyNonce,
2328 u8 * TxRSC,
2329 u8 * GTK,
2330 u8 * RSNIE,
62eb734b 2331 u8 RSNIE_Len, struct rt_eapol_packet * pMsg)
91980990 2332{
96b3c83d 2333 BOOLEAN bWPA2 = FALSE;
51126deb 2334 u8 KeyDescVer;
91980990 2335
ec278fa2 2336 /* Choose WPA2 or not */
ca97b838 2337 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
96b3c83d 2338 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
ca97b838 2339 bWPA2 = TRUE;
91980990 2340
ec278fa2 2341 /* Init Packet and Fill header */
96b3c83d
BZ
2342 pMsg->ProVer = EAPOL_VER;
2343 pMsg->ProType = EAPOLKey;
91980990 2344
ec278fa2 2345 /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */
51126deb 2346 SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
91980990 2347
ec278fa2 2348 /* Fill in EAPoL descriptor */
ca97b838
BZ
2349 if (bWPA2)
2350 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2351 else
2352 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
91980990 2353
ec278fa2 2354 /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */
ca97b838 2355 {
ec278fa2
BZ
2356 /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */
2357 /* When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. */
96b3c83d
BZ
2358 KeyDescVer =
2359 (((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
2360 || (GroupKeyWepStatus ==
2361 Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES)
2362 : (DESC_TYPE_TKIP));
ca97b838
BZ
2363 }
2364
2365 pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2366
ec278fa2 2367 /* Specify Key Type as Group(0) or Pairwise(1) */
ca97b838
BZ
2368 if (MsgType >= EAPOL_GROUP_MSG_1)
2369 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
96b3c83d 2370 else
ca97b838 2371 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
91980990 2372
ec278fa2 2373 /* Specify Key Index, only group_msg1_WPA1 */
ca97b838
BZ
2374 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2375 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
91980990 2376
ca97b838
BZ
2377 if (MsgType == EAPOL_PAIR_MSG_3)
2378 pMsg->KeyDesc.KeyInfo.Install = 1;
2379
96b3c83d
BZ
2380 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)
2381 || (MsgType == EAPOL_GROUP_MSG_1))
ca97b838
BZ
2382 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
2383
2384 if (MsgType != EAPOL_PAIR_MSG_1)
2385 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
2386
2387 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
96b3c83d
BZ
2388 (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) {
2389 pMsg->KeyDesc.KeyInfo.Secure = 1;
2390 }
ca97b838
BZ
2391
2392 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
96b3c83d
BZ
2393 (MsgType == EAPOL_GROUP_MSG_1))) {
2394 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2395 }
ec278fa2 2396 /* key Information element has done. */
51126deb
BZ
2397 *(u16 *) (&pMsg->KeyDesc.KeyInfo) =
2398 cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo));
91980990 2399
ec278fa2 2400 /* Fill in Key Length */
91980990 2401 {
96b3c83d 2402 if (MsgType >= EAPOL_GROUP_MSG_1) {
ec278fa2 2403 /* the length of group key cipher */
96b3c83d
BZ
2404 pMsg->KeyDesc.KeyLength[1] =
2405 ((GroupKeyWepStatus ==
2406 Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH :
2407 LEN_AES_KEY);
2408 } else {
ec278fa2 2409 /* the length of pairwise key cipher */
96b3c83d
BZ
2410 pMsg->KeyDesc.KeyLength[1] =
2411 ((pEntry->WepStatus ==
2412 Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY :
2413 LEN_AES_KEY);
ca97b838
BZ
2414 }
2415 }
91980990 2416
ec278fa2 2417 /* Fill in replay counter */
96b3c83d
BZ
2418 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter,
2419 LEN_KEY_DESC_REPLAY);
91980990 2420
ec278fa2
BZ
2421 /* Fill Key Nonce field */
2422 /* ANonce : pairwise_msg1 & pairwise_msg3 */
2423 /* SNonce : pairwise_msg2 */
2424 /* GNonce : group_msg1_wpa1 */
96b3c83d
BZ
2425 if ((MsgType <= EAPOL_PAIR_MSG_3)
2426 || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
2427 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce,
2428 LEN_KEY_DESC_NONCE);
91980990 2429
ec278fa2 2430 /* Fill key IV - WPA2 as 0, WPA1 as random */
96b3c83d 2431 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) {
ec278fa2 2432 /* Suggest IV be random number plus some number, */
96b3c83d
BZ
2433 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16],
2434 LEN_KEY_DESC_IV);
2435 pMsg->KeyDesc.KeyIv[15] += 2;
2436 }
ec278fa2
BZ
2437 /* Fill Key RSC field */
2438 /* It contains the RSC for the GTK being installed. */
96b3c83d
BZ
2439 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2)
2440 || (MsgType == EAPOL_GROUP_MSG_1)) {
2441 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2442 }
ec278fa2 2443 /* Clear Key MIC field for MIC calculation later */
96b3c83d 2444 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
ca97b838
BZ
2445
2446 ConstructEapolKeyData(pEntry,
96b3c83d
BZ
2447 GroupKeyWepStatus,
2448 KeyDescVer,
2449 MsgType,
2450 DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg);
ca97b838 2451
ec278fa2 2452 /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */
96b3c83d 2453 if (MsgType != EAPOL_PAIR_MSG_1) {
ca97b838 2454 CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
96b3c83d 2455 }
ca97b838 2456
96b3c83d
BZ
2457 DBGPRINT(RT_DEBUG_TRACE,
2458 ("===> ConstructEapolMsg for %s %s\n",
2459 ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2460 DBGPRINT(RT_DEBUG_TRACE,
2461 (" Body length = %d \n",
51126deb 2462 CONV_ARRARY_TO_u16(pMsg->Body_Len)));
96b3c83d
BZ
2463 DBGPRINT(RT_DEBUG_TRACE,
2464 (" Key length = %d \n",
51126deb 2465 CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength)));
ca97b838 2466
91980990
GKH
2467}
2468
2469/*
2470 ========================================================================
2471
2472 Routine Description:
ca97b838 2473 Construct the Key Data field of EAPoL message
91980990
GKH
2474
2475 Arguments:
ca97b838
BZ
2476 pAd Pointer to our adapter
2477 Elem Message body
91980990
GKH
2478
2479 Return Value:
ca97b838 2480 None
91980990
GKH
2481
2482 Note:
2483
2484 ========================================================================
2485*/
62eb734b 2486void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
51126deb
BZ
2487 u8 GroupKeyWepStatus,
2488 u8 keyDescVer,
2489 u8 MsgType,
2490 u8 DefaultKeyIdx,
2491 u8 * GTK,
2492 u8 * RSNIE,
62eb734b 2493 u8 RSNIE_LEN, struct rt_eapol_packet * pMsg)
91980990 2494{
51126deb
BZ
2495 u8 *mpool, *Key_Data, *Rc4GTK;
2496 u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)];
2497 unsigned long data_offset;
96b3c83d 2498 BOOLEAN bWPA2Capable = FALSE;
62eb734b 2499 struct rt_rtmp_adapter *pAd = pEntry->pAd;
96b3c83d 2500 BOOLEAN GTK_Included = FALSE;
ca97b838 2501
ec278fa2 2502 /* Choose WPA2 or not */
ca97b838 2503 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
96b3c83d 2504 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
ca97b838
BZ
2505 bWPA2Capable = TRUE;
2506
2507 if (MsgType == EAPOL_PAIR_MSG_1 ||
96b3c83d 2508 MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
ca97b838 2509 return;
91980990 2510
ec278fa2 2511 /* allocate memory pool */
51126deb 2512 os_alloc_mem(NULL, (u8 **) & mpool, 1500);
91980990 2513
96b3c83d 2514 if (mpool == NULL)
ca97b838
BZ
2515 return;
2516
2517 /* Rc4GTK Len = 512 */
51126deb 2518 Rc4GTK = (u8 *) ROUND_UP(mpool, 4);
ca97b838 2519 /* Key_Data Len = 512 */
51126deb 2520 Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4);
ca97b838
BZ
2521
2522 NdisZeroMemory(Key_Data, 512);
51126deb 2523 SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
ca97b838
BZ
2524 data_offset = 0;
2525
ec278fa2 2526 /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */
96b3c83d
BZ
2527 if (RSNIE_LEN
2528 && ((MsgType == EAPOL_PAIR_MSG_2)
2529 || (MsgType == EAPOL_PAIR_MSG_3))) {
51126deb
BZ
2530 u8 *pmkid_ptr = NULL;
2531 u8 pmkid_len = 0;
ca97b838
BZ
2532
2533 RTMPInsertRSNIE(&Key_Data[data_offset],
96b3c83d
BZ
2534 &data_offset,
2535 RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len);
ca97b838
BZ
2536 }
2537
ec278fa2 2538 /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */
96b3c83d
BZ
2539 if (bWPA2Capable
2540 && ((MsgType == EAPOL_PAIR_MSG_3)
2541 || (MsgType == EAPOL_GROUP_MSG_1))) {
ec278fa2 2542 /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */
96b3c83d 2543 Key_Data[data_offset + 0] = 0xDD;
ca97b838 2544
96b3c83d 2545 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
ec278fa2 2546 Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */
96b3c83d 2547 } else {
ec278fa2 2548 Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */
ca97b838
BZ
2549 }
2550
96b3c83d
BZ
2551 Key_Data[data_offset + 2] = 0x00;
2552 Key_Data[data_offset + 3] = 0x0F;
2553 Key_Data[data_offset + 4] = 0xAC;
2554 Key_Data[data_offset + 5] = 0x01;
ca97b838 2555
ec278fa2 2556 /* GTK KDE format - 802.11i-2004 Figure-43x */
96b3c83d 2557 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
ec278fa2 2558 Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */
ca97b838
BZ
2559
2560 data_offset += 8;
2561 }
2562
ec278fa2
BZ
2563 /* Encapsulate GTK */
2564 /* Only for pairwise_msg3_WPA2 and group_msg1 */
96b3c83d
BZ
2565 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
2566 || (MsgType == EAPOL_GROUP_MSG_1)) {
ec278fa2 2567 /* Fill in GTK */
96b3c83d
BZ
2568 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
2569 NdisMoveMemory(&Key_Data[data_offset], GTK,
2570 LEN_AES_KEY);
ca97b838 2571 data_offset += LEN_AES_KEY;
96b3c83d
BZ
2572 } else {
2573 NdisMoveMemory(&Key_Data[data_offset], GTK,
2574 TKIP_GTK_LENGTH);
ca97b838
BZ
2575 data_offset += TKIP_GTK_LENGTH;
2576 }
2577
2578 GTK_Included = TRUE;
2579 }
2580
ec278fa2
BZ
2581 /* This whole key-data field shall be encrypted if a GTK is included. */
2582 /* Encrypt the data material in key data field with KEK */
96b3c83d 2583 if (GTK_Included) {
ec278fa2 2584 /*hex_dump("GTK_Included", Key_Data, data_offset); */
91980990 2585
96b3c83d 2586 if ((keyDescVer == DESC_TYPE_AES)) {
51126deb
BZ
2587 u8 remainder = 0;
2588 u8 pad_len = 0;
ca97b838 2589
ec278fa2
BZ
2590 /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */
2591 /* shall be used to encrypt the Key Data field using the KEK field from */
2592 /* the derived PTK. */
ca97b838 2593
ec278fa2
BZ
2594 /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */
2595 /* shall be padded before encrypting if the key data length is less than 16 */
2596 /* octets or if it is not a multiple of 8. The padding consists of appending */
2597 /* a single octet 0xdd followed by zero or more 0x00 octets. */
96b3c83d 2598 if ((remainder = data_offset & 0x07) != 0) {
51126deb 2599 int i;
ca97b838
BZ
2600
2601 pad_len = (8 - remainder);
2602 Key_Data[data_offset] = 0xDD;
2603 for (i = 1; i < pad_len; i++)
2604 Key_Data[data_offset + i] = 0;
2605
2606 data_offset += pad_len;
96b3c83d 2607 }
ca97b838 2608
96b3c83d
BZ
2609 AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data,
2610 data_offset, Rc4GTK);
ec278fa2 2611 /* AES wrap function will grow 8 bytes in length */
96b3c83d
BZ
2612 data_offset += 8;
2613 } else {
2614 /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
2615 using the KEK field from the derived PTK. */
ca97b838 2616
ec278fa2
BZ
2617 /* PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) */
2618 /* put TxTsc in Key RSC field */
2619 pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */
ca97b838 2620
ec278fa2 2621 /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */
96b3c83d
BZ
2622 NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv,
2623 LEN_KEY_DESC_IV);
2624 NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16],
2625 LEN_EAP_EK);
ec278fa2 2626 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */
96b3c83d
BZ
2627 pAd->PrivateInfo.FCSCRC32 =
2628 RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data,
2629 data_offset);
2630 WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK,
2631 Key_Data, data_offset);
ca97b838 2632 }
91980990 2633
ca97b838 2634 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
96b3c83d 2635 } else {
ca97b838 2636 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
91980990
GKH
2637 }
2638
ec278fa2 2639 /* Update key data length field and total body length */
51126deb
BZ
2640 SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
2641 INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset);
91980990 2642
ca97b838 2643 os_free_mem(NULL, mpool);
91980990
GKH
2644
2645}
2646
2647/*
2648 ========================================================================
2649
2650 Routine Description:
ca97b838 2651 Calcaulate MIC. It is used during 4-ways handsharking.
91980990
GKH
2652
2653 Arguments:
2654 pAd - pointer to our pAdapter context
ca97b838 2655 PeerWepStatus - indicate the encryption type
91980990
GKH
2656
2657 Return Value:
2658
2659 Note:
2660
2661 ========================================================================
2662*/
51126deb 2663static void CalculateMIC(u8 KeyDescVer,
62eb734b 2664 u8 * PTK, struct rt_eapol_packet * pMsg)
91980990 2665{
51126deb
BZ
2666 u8 *OutBuffer;
2667 unsigned long FrameLen = 0;
2668 u8 mic[LEN_KEY_DESC_MIC];
2669 u8 digest[80];
91980990 2670
ec278fa2 2671 /* allocate memory for MIC calculation */
51126deb 2672 os_alloc_mem(NULL, (u8 **) & OutBuffer, 512);
ca97b838 2673
96b3c83d 2674 if (OutBuffer == NULL) {
06aea994 2675 DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n"));
91980990 2676 return;
96b3c83d 2677 }
ec278fa2 2678 /* make a frame for calculating MIC. */
96b3c83d 2679 MakeOutgoingFrame(OutBuffer, &FrameLen,
51126deb 2680 CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg,
96b3c83d 2681 END_OF_ARGS);
91980990 2682
ca97b838 2683 NdisZeroMemory(mic, sizeof(mic));
91980990 2684
ec278fa2 2685 /* Calculate MIC */
96b3c83d
BZ
2686 if (KeyDescVer == DESC_TYPE_AES) {
2687 HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest,
2688 SHA1_DIGEST_SIZE);
ca97b838 2689 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
96b3c83d
BZ
2690 } else {
2691 HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic,
2692 MD5_DIGEST_SIZE);
ca97b838 2693 }
91980990 2694
ec278fa2 2695 /* store the calculated MIC */
ca97b838 2696 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
91980990 2697
ca97b838 2698 os_free_mem(NULL, OutBuffer);
91980990
GKH
2699}
2700
91980990
GKH
2701/*
2702 ========================================================================
2703
2704 Routine Description:
ca97b838 2705 Some received frames can't decrypt by Asic, so decrypt them by software.
91980990
GKH
2706
2707 Arguments:
2708 pAd - pointer to our pAdapter context
ca97b838 2709 PeerWepStatus - indicate the encryption type
91980990
GKH
2710
2711 Return Value:
ca97b838
BZ
2712 NDIS_STATUS_SUCCESS - decryption successful
2713 NDIS_STATUS_FAILURE - decryption failure
91980990
GKH
2714
2715 ========================================================================
2716*/
62eb734b
BZ
2717int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd,
2718 struct rt_rx_blk *pRxBlk,
96b3c83d 2719 IN NDIS_802_11_ENCRYPTION_STATUS
62eb734b 2720 GroupCipher, struct rt_cipher_key *pShard_key)
91980990 2721{
62eb734b 2722 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
91980990 2723
ec278fa2 2724 /* handle WEP decryption */
96b3c83d
BZ
2725 if (GroupCipher == Ndis802_11Encryption1Enabled) {
2726 if (RTMPSoftDecryptWEP
2727 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2728 pShard_key)) {
ca97b838 2729
ec278fa2 2730 /*Minus IV[4] & ICV[4] */
ca97b838 2731 pRxWI->MPDUtotalByteCount -= 8;
96b3c83d
BZ
2732 } else {
2733 DBGPRINT(RT_DEBUG_ERROR,
2734 ("ERROR : Software decrypt WEP data fails.\n"));
ec278fa2 2735 /* give up this frame */
ca97b838
BZ
2736 return NDIS_STATUS_FAILURE;
2737 }
2738 }
ec278fa2 2739 /* handle TKIP decryption */
96b3c83d
BZ
2740 else if (GroupCipher == Ndis802_11Encryption2Enabled) {
2741 if (RTMPSoftDecryptTKIP
2742 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0,
2743 pShard_key)) {
ca97b838 2744
ec278fa2 2745 /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */
ca97b838 2746 pRxWI->MPDUtotalByteCount -= 20;
96b3c83d
BZ
2747 } else {
2748 DBGPRINT(RT_DEBUG_ERROR,
2749 ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
ec278fa2 2750 /* give up this frame */
ca97b838 2751 return NDIS_STATUS_FAILURE;
96b3c83d 2752 }
ca97b838 2753 }
ec278fa2 2754 /* handle AES decryption */
96b3c83d
BZ
2755 else if (GroupCipher == Ndis802_11Encryption3Enabled) {
2756 if (RTMPSoftDecryptAES
2757 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2758 pShard_key)) {
91980990 2759
ec278fa2 2760 /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */
ca97b838 2761 pRxWI->MPDUtotalByteCount -= 16;
96b3c83d
BZ
2762 } else {
2763 DBGPRINT(RT_DEBUG_ERROR,
2764 ("ERROR : RTMPSoftDecryptAES Failed\n"));
ec278fa2 2765 /* give up this frame */
ca97b838
BZ
2766 return NDIS_STATUS_FAILURE;
2767 }
96b3c83d 2768 } else {
ec278fa2 2769 /* give up this frame */
ca97b838
BZ
2770 return NDIS_STATUS_FAILURE;
2771 }
91980990 2772
ca97b838 2773 return NDIS_STATUS_SUCCESS;
91980990 2774
ca97b838 2775}
91980990 2776
51126deb
BZ
2777u8 *GetSuiteFromRSNIE(u8 *rsnie,
2778 u32 rsnie_len, u8 type, u8 * count)
ca97b838 2779{
62eb734b 2780 struct rt_eid * pEid;
51126deb
BZ
2781 int len;
2782 u8 *pBuf;
2783 int offset = 0;
62eb734b 2784 struct rt_rsnie_auth *pAkm;
51126deb 2785 u16 acount;
96b3c83d
BZ
2786 BOOLEAN isWPA2 = FALSE;
2787
62eb734b 2788 pEid = (struct rt_eid *) rsnie;
ec278fa2 2789 len = rsnie_len - 2; /* exclude IE and length */
51126deb 2790 pBuf = (u8 *)& pEid->Octet[0];
ca97b838 2791
ec278fa2 2792 /* set default value */
ca97b838
BZ
2793 *count = 0;
2794
ec278fa2 2795 /* Check length */
96b3c83d 2796 if ((len <= 0) || (pEid->Len != len)) {
ca97b838
BZ
2797 DBGPRINT_ERR(("%s : The length is invalid\n", __func__));
2798 return NULL;
91980990 2799 }
ec278fa2 2800 /* Check WPA or WPA2 */
96b3c83d 2801 if (pEid->Eid == IE_WPA) {
62eb734b 2802 struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf;
51126deb 2803 u16 ucount;
91980990 2804
62eb734b 2805 if (len < sizeof(struct rt_rsnie)) {
96b3c83d
BZ
2806 DBGPRINT_ERR(("%s : The length is too short for WPA\n",
2807 __func__));
ca97b838
BZ
2808 return NULL;
2809 }
ec278fa2 2810 /* Get the count of pairwise cipher */
ca97b838 2811 ucount = cpu2le16(pRsnie->ucount);
96b3c83d
BZ
2812 if (ucount > 2) {
2813 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount));
ca97b838
BZ
2814 return NULL;
2815 }
ec278fa2 2816 /* Get the group cipher */
96b3c83d 2817 if (type == GROUP_SUITE) {
ca97b838
BZ
2818 *count = 1;
2819 return pRsnie->mcast;
2820 }
ec278fa2 2821 /* Get the pairwise cipher suite */
96b3c83d
BZ
2822 else if (type == PAIRWISE_SUITE) {
2823 DBGPRINT(RT_DEBUG_TRACE,
2824 ("%s : The count of pairwise cipher is %d\n",
2825 __func__, ucount));
ca97b838
BZ
2826 *count = ucount;
2827 return pRsnie->ucast[0].oui;
96b3c83d 2828 }
91980990 2829
62eb734b 2830 offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1));
91980990 2831
96b3c83d 2832 } else if (pEid->Eid == IE_RSN) {
62eb734b 2833 struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf;
51126deb 2834 u16 ucount;
91980990 2835
ca97b838 2836 isWPA2 = TRUE;
91980990 2837
62eb734b 2838 if (len < sizeof(struct rt_rsnie2)) {
96b3c83d
BZ
2839 DBGPRINT_ERR(("%s : The length is too short for WPA2\n",
2840 __func__));
ca97b838
BZ
2841 return NULL;
2842 }
ec278fa2 2843 /* Get the count of pairwise cipher */
ca97b838 2844 ucount = cpu2le16(pRsnie->ucount);
96b3c83d
BZ
2845 if (ucount > 2) {
2846 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount));
ca97b838
BZ
2847 return NULL;
2848 }
ec278fa2 2849 /* Get the group cipher */
96b3c83d 2850 if (type == GROUP_SUITE) {
ca97b838
BZ
2851 *count = 1;
2852 return pRsnie->mcast;
2853 }
ec278fa2 2854 /* Get the pairwise cipher suite */
96b3c83d
BZ
2855 else if (type == PAIRWISE_SUITE) {
2856 DBGPRINT(RT_DEBUG_TRACE,
2857 ("%s : The count of pairwise cipher is %d\n",
2858 __func__, ucount));
ca97b838
BZ
2859 *count = ucount;
2860 return pRsnie->ucast[0].oui;
2861 }
91980990 2862
62eb734b 2863 offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1));
ca97b838 2864
96b3c83d 2865 } else {
ca97b838
BZ
2866 DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __func__, pEid->Eid));
2867 return NULL;
2868 }
91980990 2869
ec278fa2 2870 /* skip group cipher and pairwise cipher suite */
ca97b838
BZ
2871 pBuf += offset;
2872 len -= offset;
91980990 2873
62eb734b 2874 if (len < sizeof(struct rt_rsnie_auth)) {
96b3c83d
BZ
2875 DBGPRINT_ERR(("%s : The length of RSNIE is too short\n",
2876 __func__));
ca97b838
BZ
2877 return NULL;
2878 }
ec278fa2 2879 /* pointer to AKM count */
62eb734b 2880 pAkm = (struct rt_rsnie_auth *)pBuf;
91980990 2881
ec278fa2 2882 /* Get the count of pairwise cipher */
ca97b838 2883 acount = cpu2le16(pAkm->acount);
96b3c83d 2884 if (acount > 2) {
ca97b838 2885 DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n",
96b3c83d 2886 __func__, acount));
ca97b838 2887 return NULL;
96b3c83d 2888 }
ec278fa2 2889 /* Get the AKM suite */
96b3c83d 2890 if (type == AKM_SUITE) {
ca97b838 2891 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
96b3c83d 2892 __func__, acount));
ca97b838
BZ
2893 *count = acount;
2894 return pAkm->auth[0].oui;
96b3c83d 2895 }
62eb734b 2896 offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1));
91980990 2897
ca97b838
BZ
2898 pBuf += offset;
2899 len -= offset;
2900
ec278fa2 2901 /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */
96b3c83d 2902 if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) {
ec278fa2 2903 /* Skip RSN capability and PMKID-Count */
ca97b838
BZ
2904 pBuf += (sizeof(RSN_CAPABILITIES) + 2);
2905 len -= (sizeof(RSN_CAPABILITIES) + 2);
2906
ec278fa2 2907 /* Get PMKID */
96b3c83d 2908 if (type == PMKID_LIST) {
ca97b838
BZ
2909 *count = 1;
2910 return pBuf;
96b3c83d
BZ
2911 }
2912 } else {
ca97b838
BZ
2913 DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __func__));
2914 return NULL;
2915 }
2916
2917 *count = 0;
ec278fa2 2918 /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */
ca97b838
BZ
2919 return NULL;
2920
91980990
GKH
2921}
2922
51126deb 2923void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len)
ca97b838 2924{
51126deb
BZ
2925 u8 *pSuite = NULL;
2926 u8 count;
91980990 2927
ca97b838 2928 hex_dump("RSNIE", rsnie, rsnie_len);
91980990 2929
ec278fa2 2930 /* group cipher */
6aed5295
JP
2931 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count);
2932 if (pSuite != NULL) {
96b3c83d 2933 hex_dump("group cipher", pSuite, 4 * count);
ca97b838 2934 }
ec278fa2 2935 /* pairwise cipher */
6aed5295
JP
2936 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count);
2937 if (pSuite != NULL) {
96b3c83d 2938 hex_dump("pairwise cipher", pSuite, 4 * count);
ca97b838 2939 }
ec278fa2 2940 /* AKM */
6aed5295
JP
2941 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count);
2942 if (pSuite != NULL) {
96b3c83d 2943 hex_dump("AKM suite", pSuite, 4 * count);
ca97b838 2944 }
ec278fa2 2945 /* PMKID */
6aed5295
JP
2946 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count);
2947 if (pSuite != NULL) {
ca97b838
BZ
2948 hex_dump("PMKID", pSuite, LEN_PMKID);
2949 }
91980990 2950
ca97b838 2951}
91980990 2952
51126deb
BZ
2953void RTMPInsertRSNIE(u8 *pFrameBuf,
2954 unsigned long *pFrameLen,
2955 u8 *rsnie_ptr,
2956 u8 rsnie_len,
2957 u8 *pmkid_ptr, u8 pmkid_len)
ca97b838 2958{
51126deb
BZ
2959 u8 *pTmpBuf;
2960 unsigned long TempLen = 0;
2961 u8 extra_len = 0;
2962 u16 pmk_count = 0;
2963 u8 ie_num;
2964 u8 total_len = 0;
2965 u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC };
ca97b838
BZ
2966
2967 pTmpBuf = pFrameBuf;
2968
2969 /* PMKID-List Must larger than 0 and the multiple of 16. */
96b3c83d 2970 if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) {
51126deb 2971 extra_len = sizeof(u16)+ pmkid_len;
91980990 2972
ca97b838
BZ
2973 pmk_count = (pmkid_len >> 4);
2974 pmk_count = cpu2le16(pmk_count);
96b3c83d
BZ
2975 } else {
2976 DBGPRINT(RT_DEBUG_WARN,
2977 ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
2978 __func__, pmkid_len));
ca97b838 2979 }
91980990 2980
96b3c83d 2981 if (rsnie_len != 0) {
ca97b838
BZ
2982 ie_num = IE_WPA;
2983 total_len = rsnie_len;
91980990 2984
96b3c83d 2985 if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) {
ca97b838
BZ
2986 ie_num = IE_RSN;
2987 total_len += extra_len;
96b3c83d 2988 }
91980990 2989
ca97b838 2990 /* construct RSNIE body */
96b3c83d
BZ
2991 MakeOutgoingFrame(pTmpBuf, &TempLen,
2992 1, &ie_num,
2993 1, &total_len,
2994 rsnie_len, rsnie_ptr, END_OF_ARGS);
ca97b838
BZ
2995
2996 pTmpBuf += TempLen;
2997 *pFrameLen = *pFrameLen + TempLen;
91980990 2998
96b3c83d 2999 if (ie_num == IE_RSN) {
ca97b838 3000 /* Insert PMKID-List field */
96b3c83d
BZ
3001 if (extra_len > 0) {
3002 MakeOutgoingFrame(pTmpBuf, &TempLen,
3003 2, &pmk_count,
3004 pmkid_len, pmkid_ptr,
3005 END_OF_ARGS);
ca97b838
BZ
3006
3007 pTmpBuf += TempLen;
3008 *pFrameLen = *pFrameLen + TempLen;
96b3c83d 3009 }
91980990
GKH
3010 }
3011 }
91980990 3012
ca97b838 3013 return;
91980990 3014}