]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/rt2860/common/cmm_wpa.c
Fix common misspellings
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / rt2860 / common / cmm_wpa.c
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"
39 /* WPA OUI */
40 u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 };
41 u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 };
42 u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 };
43 u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 };
44 u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 };
45 u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 };
46 u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 };
47 u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 };
48
49 /* WPA2 OUI */
50 u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 };
51 u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 };
52 u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 };
53 u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 };
54 u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 };
55 u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 };
56
57 static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
58 u8 GroupKeyWepStatus,
59 u8 keyDescVer,
60 u8 MsgType,
61 u8 DefaultKeyIdx,
62 u8 * GTK,
63 u8 * RSNIE,
64 u8 RSNIE_LEN, struct rt_eapol_packet * pMsg);
65
66 static void CalculateMIC(u8 KeyDescVer,
67 u8 * PTK, struct rt_eapol_packet * pMsg);
68
69 static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
70
71 static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd,
72 struct rt_mlme_queue_elem *Elem);
73
74 static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd,
75 struct rt_mlme_queue_elem *Elem);
76
77 static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd,
78 struct rt_mlme_queue_elem *Elem);
79
80 static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
81
82 /*
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 */
90 void WpaStateMachineInit(struct rt_rtmp_adapter *pAd,
91 struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[])
92 {
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);
107 }
108
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 */
118 void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
119 {
120 }
121
122 void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
123 {
124 }
125
126 void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
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 */
137 void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
138 {
139 struct rt_mac_table_entry *pEntry;
140 struct rt_header_802_11 * pHeader;
141
142 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
143
144 pHeader = (struct rt_header_802_11 *) Elem->Msg;
145
146 /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */
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 }
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 */
190 void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
191 {
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;
196
197 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
198
199 pHeader = (struct rt_header_802_11 *) Elem->Msg;
200 pEapol_packet =
201 (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
202
203 NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo));
204 NdisMoveMemory((u8 *)& peerKeyInfo,
205 (u8 *)& pEapol_packet->KeyDesc.KeyInfo,
206 sizeof(struct rt_key_info));
207
208 hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet,
209 (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
210
211 *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo));
212
213 do {
214 pEntry = MacTableLookup(pAd, pHeader->Addr2);
215
216 if (!pEntry
217 || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
218 break;
219
220 if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
221 break;
222
223 DBGPRINT(RT_DEBUG_TRACE,
224 ("Receive EAPoL-Key frame from STA %pMF\n",
225 pEntry->Addr));
226
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 }
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. */
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 }
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. */
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 }
251 /* Check if this STA is in class 3 state and the WPA state is started */
252 if ((pEntry->Sst == SST_ASSOC)
253 && (pEntry->WpaState >= AS_INITPSK)) {
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. */
258 if (peerKeyInfo.KeyAck == 1) {
259 /* The frame is snet by Authenticator. */
260 /* So the Supplicant side shall handle this. */
261
262 if ((peerKeyInfo.Secure == 0)
263 && (peerKeyInfo.Request == 0)
264 && (peerKeyInfo.Error == 0)
265 && (peerKeyInfo.KeyType == PAIRWISEKEY)) {
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) */
270 if (peerKeyInfo.KeyMic == 0)
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)) {
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]) */
284 if (peerKeyInfo.KeyType == PAIRWISEKEY)
285 PeerPairMsg3Action(pAd, pEntry,
286 Elem);
287 else
288 PeerGroupMsg1Action(pAd, pEntry,
289 Elem);
290 }
291 } else {
292 /* The frame is snet by Supplicant. */
293 /* So the Authenticator side shall handle this. */
294 if ((peerKeyInfo.Request == 0) &&
295 (peerKeyInfo.Error == 0) &&
296 (peerKeyInfo.KeyMic == 1)) {
297 if (peerKeyInfo.Secure == 0
298 && peerKeyInfo.KeyType ==
299 PAIRWISEKEY) {
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 */
303 if (CONV_ARRARY_TO_u16
304 (pEapol_packet->KeyDesc.
305 KeyDataLen) == 0) {
306 PeerPairMsg4Action(pAd,
307 pEntry,
308 Elem);
309 } else {
310 PeerPairMsg2Action(pAd,
311 pEntry,
312 Elem);
313 }
314 } else if (peerKeyInfo.Secure == 1
315 && peerKeyInfo.KeyType ==
316 PAIRWISEKEY) {
317 /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */
318 /* Process message 4 of 4-way HS in WPA2 */
319 PeerPairMsg4Action(pAd, pEntry,
320 Elem);
321 } else if (peerKeyInfo.Secure == 1
322 && peerKeyInfo.KeyType ==
323 GROUPKEY) {
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 */
326 PeerGroupMsg2Action(pAd, pEntry,
327 &Elem->
328 Msg
329 [LENGTH_802_11],
330 (Elem->
331 MsgLen -
332 LENGTH_802_11));
333 }
334 }
335 }
336 }
337 } while (FALSE);
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.
347
348 Arguments:
349 pAd Pointer to our adapter
350 void * Pointer to outgoing Ndis frame
351 NumberOfFrag Number of fragment required
352
353 Return Value:
354 None
355
356 Note:
357
358 ========================================================================
359 */
360 void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd,
361 struct rt_mac_table_entry *pEntry,
362 u8 *pHeader802_3,
363 u32 HdrLen,
364 u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame)
365 {
366 void *pPacket;
367 int Status;
368
369 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
370 return;
371
372 do {
373 /* build a NDIS packet */
374 Status =
375 RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen,
376 pData, DataLen);
377 if (Status != NDIS_STATUS_SUCCESS)
378 break;
379
380 if (bClearFrame)
381 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
382 else
383 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
384 {
385 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
386
387 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */
388 if (pEntry->apidx != 0)
389 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket,
390 pEntry->
391 apidx);
392
393 RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
394 RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
395 }
396
397 {
398 /* send out the packet */
399 Status = STASendPacket(pAd, pPacket);
400 if (Status == NDIS_STATUS_SUCCESS) {
401 u8 Index;
402
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 */
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);
420 }
421 }
422 }
423
424 } while (FALSE);
425 }
426
427 /*
428 ==========================================================================
429 Description:
430 This is a function to initialize 4-way handshake
431
432 Return:
433
434 ==========================================================================
435 */
436 void WPAStart4WayHS(struct rt_rtmp_adapter *pAd,
437 struct rt_mac_table_entry *pEntry, unsigned long TimeInterval)
438 {
439 u8 Header802_3[14];
440 struct rt_eapol_packet EAPOLPKT;
441 u8 *pBssid = NULL;
442 u8 group_cipher = Ndis802_11WEPDisabled;
443
444 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
445
446 if (RTMP_TEST_FLAG
447 (pAd,
448 fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
449 {
450 DBGPRINT(RT_DEBUG_ERROR,
451 ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
452 return;
453 }
454
455 if (pBssid == NULL) {
456 DBGPRINT(RT_DEBUG_ERROR,
457 ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
458 return;
459 }
460 /* Check the status */
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 }
466
467 /* Increment replay counter by 1 */
468 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
469
470 /* Randomly generate ANonce */
471 GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce);
472
473 /* Construct EAPoL message - Pairwise Msg 1 */
474 /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
475 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
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 */
481 &EAPOLPKT);
482
483 /* Make outgoing frame */
484 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
485 RTMPToWirelessSta(pAd, pEntry, Header802_3,
486 LENGTH_802_3, (u8 *)& EAPOLPKT,
487 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
488 (pEntry->PortSecured ==
489 WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
490
491 /* Trigger Retry Timer */
492 RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
493
494 /* Update State */
495 pEntry->WpaState = AS_PTKSTART;
496
497 DBGPRINT(RT_DEBUG_TRACE,
498 ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
499
500 }
501
502 /*
503 ========================================================================
504
505 Routine Description:
506 Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
507
508 Arguments:
509 pAd Pointer to our adapter
510 Elem Message body
511
512 Return Value:
513 None
514
515 Note:
516
517 ========================================================================
518 */
519 void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd,
520 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
521 {
522 u8 PTK[80];
523 u8 Header802_3[14];
524 struct rt_eapol_packet * pMsg1;
525 u32 MsgLen;
526 struct rt_eapol_packet EAPOLPKT;
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;
532
533 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
534
535 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
536 return;
537
538 if (Elem->MsgLen <
539 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
540 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
541 return;
542
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 }
550
551 /* Store the received frame */
552 pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
553 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
554
555 /* Sanity Check peer Pairwise message 1 - Replay Counter */
556 if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry)
557 == FALSE)
558 return;
559
560 /* Store Replay counter, it will use to verify message 3 and construct message 2 */
561 NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter,
562 LEN_KEY_DESC_REPLAY);
563
564 /* Store ANonce */
565 NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce,
566 LEN_KEY_DESC_NONCE);
567
568 /* Generate random SNonce */
569 GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce);
570
571 {
572 /* Calculate PTK(ANonce, SNonce) */
573 WpaDerivePTK(pAd,
574 pmk_ptr,
575 pEntry->ANonce,
576 pEntry->Addr,
577 pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK);
578
579 /* Save key to PTK entry */
580 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
581 }
582
583 /* Update WpaState */
584 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
585
586 /* Construct EAPoL message - Pairwise Msg 2 */
587 /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */
588 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
589 ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */
590 pEntry->SNonce, NULL, /* TxRsc */
591 NULL, /* GTK */
592 (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
593
594 /* Make outgoing frame */
595 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
596
597 RTMPToWirelessSta(pAd, pEntry,
598 Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT,
599 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
600
601 DBGPRINT(RT_DEBUG_TRACE,
602 ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
603 }
604
605 /*
606 ==========================================================================
607 Description:
608 When receiving the second packet of 4-way pairwisekey handshake.
609 Return:
610 ==========================================================================
611 */
612 void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd,
613 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
614 {
615 u8 PTK[80];
616 BOOLEAN Cancelled;
617 struct rt_header_802_11 * pHeader;
618 struct rt_eapol_packet EAPOLPKT;
619 struct rt_eapol_packet * pMsg2;
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;
630
631 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
632
633 if ((!pEntry) || (!pEntry->ValidAsCLI))
634 return;
635
636 if (Elem->MsgLen <
637 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
638 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
639 return;
640
641 /* check Entry in valid State */
642 if (pEntry->WpaState < AS_PTKSTART)
643 return;
644
645 /* pointer to 802.11 header */
646 pHeader = (struct rt_header_802_11 *) Elem->Msg;
647
648 /* skip 802.11_header(24-byte) and LLC_header(8) */
649 pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
650 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
651
652 /* Store SNonce */
653 NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce,
654 LEN_KEY_DESC_NONCE);
655
656 {
657 /* Derive PTK */
658 WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */
659 (u8 *) pBssid, pEntry->SNonce, /* SNONCE */
660 pEntry->Addr, PTK, LEN_PTK);
661
662 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
663 }
664
665 /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */
666 if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry)
667 == FALSE)
668 return;
669
670 do {
671 /* delete retry timer */
672 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
673
674 /* Change state */
675 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
676
677 /* Increment replay counter by 1 */
678 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
679
680 /* Construct EAPoL message - Pairwise Msg 3 */
681 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
682 ConstructEapolMsg(pEntry,
683 group_cipher,
684 EAPOL_PAIR_MSG_3,
685 default_key,
686 pEntry->ANonce,
687 TxTsc,
688 (u8 *) gtk_ptr,
689 (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
690
691 /* Make outgoing frame */
692 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
693 RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
694 (u8 *)& EAPOLPKT,
695 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
696 (pEntry->PortSecured ==
697 WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
698
699 pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
700 RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
701
702 /* Update State */
703 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
704 } while (FALSE);
705
706 DBGPRINT(RT_DEBUG_TRACE,
707 ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
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 */
727 void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd,
728 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
729 {
730 struct rt_header_802_11 * pHeader;
731 u8 Header802_3[14];
732 struct rt_eapol_packet EAPOLPKT;
733 struct rt_eapol_packet * pMsg3;
734 u32 MsgLen;
735 u8 *pCurrentAddr = NULL;
736 u8 group_cipher = Ndis802_11WEPDisabled;
737
738 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
739
740 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
741 return;
742
743 if (Elem->MsgLen <
744 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
745 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
746 return;
747
748 {
749 pCurrentAddr = pAd->CurrentAddress;
750 group_cipher = pAd->StaCfg.GroupCipher;
751
752 }
753
754 /* Record 802.11 header & the received EAPOL packet Msg3 */
755 pHeader = (struct rt_header_802_11 *) Elem->Msg;
756 pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
757 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
758
759 /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */
760 if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry)
761 == FALSE)
762 return;
763
764 /* Save Replay counter, it will use construct message 4 */
765 NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter,
766 LEN_KEY_DESC_REPLAY);
767
768 /* Double check ANonce */
769 if (!NdisEqualMemory
770 (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) {
771 return;
772 }
773 /* Construct EAPoL message - Pairwise Msg 4 */
774 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
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 */
780 0, &EAPOLPKT);
781
782 /* Update WpaState */
783 pEntry->WpaState = AS_PTKINITDONE;
784
785 /* Update pairwise key */
786 {
787 struct rt_cipher_key *pSharedKey;
788
789 pSharedKey = &pAd->SharedKey[BSS0][0];
790
791 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
792
793 /* Prepare pair-wise key information into shared key table */
794 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
795 pSharedKey->KeyLen = LEN_TKIP_EK;
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);
803
804 /* Decide its ChiperAlg */
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
812 /* Update these related information to struct rt_mac_table_entry */
813 pEntry = &pAd->MacTab.Content[BSSID_WCID];
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);
821 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
822
823 /* Update pairwise key information to ASIC Shared Key Table */
824 AsicAddSharedKeyEntry(pAd,
825 BSS0,
826 0,
827 pSharedKey->CipherAlg,
828 pSharedKey->Key,
829 pSharedKey->TxMic, pSharedKey->RxMic);
830
831 /* Update ASIC WCID attribute table and IVEIV table */
832 RTMPAddWcidAttributeEntry(pAd,
833 BSS0,
834 0, pSharedKey->CipherAlg, pEntry);
835
836 }
837
838 /* open 802.1x port control and privacy filter */
839 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
840 pEntry->AuthMode == Ndis802_11AuthModeWPA2) {
841 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
842 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
843
844 STA_PORT_SECURED(pAd);
845 /* Indicate Connected for GUI */
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 {
853 }
854
855 /* Init 802.3 header and send out */
856 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
857 RTMPToWirelessSta(pAd, pEntry,
858 Header802_3, sizeof(Header802_3),
859 (u8 *)& EAPOLPKT,
860 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
861
862 DBGPRINT(RT_DEBUG_TRACE,
863 ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
864 }
865
866 /*
867 ==========================================================================
868 Description:
869 When receiving the last packet of 4-way pairwisekey handshake.
870 Initialize 2-way groupkey handshake following.
871 Return:
872 ==========================================================================
873 */
874 void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd,
875 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
876 {
877 struct rt_eapol_packet * pMsg4;
878 struct rt_header_802_11 * pHeader;
879 u32 MsgLen;
880 BOOLEAN Cancelled;
881 u8 group_cipher = Ndis802_11WEPDisabled;
882
883 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
884
885 do {
886 if ((!pEntry) || (!pEntry->ValidAsCLI))
887 break;
888
889 if (Elem->MsgLen <
890 (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
891 sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
892 break;
893
894 if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
895 break;
896
897 /* pointer to 802.11 header */
898 pHeader = (struct rt_header_802_11 *) Elem->Msg;
899
900 /* skip 802.11_header(24-byte) and LLC_header(8) */
901 pMsg4 =
902 (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
903 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
904
905 /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */
906 if (PeerWpaMessageSanity
907 (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
908 break;
909
910 /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */
911 NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key));
912
913 /* reset IVEIV in Asic */
914 AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
915
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);
925
926 /* Set pairwise key to Asic */
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;
934
935 /* Add Pair-wise key to Asic */
936 AsicAddPairwiseKeyEntry(pAd,
937 pEntry->Addr,
938 (u8)pEntry->Aid,
939 &pEntry->PairwiseKey);
940
941 /* update WCID attribute table and IVEIV table for this entry */
942 RTMPAddWcidAttributeEntry(pAd,
943 pEntry->apidx,
944 0,
945 pEntry->PairwiseKey.CipherAlg,
946 pEntry);
947 }
948
949 /* 4. upgrade state */
950 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
951 pEntry->WpaState = AS_PTKINITDONE;
952 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
953
954 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
955 pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) {
956 pEntry->GTKState = REKEY_ESTABLISHED;
957 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
958
959 /* send wireless event - for set key done WPA2 */
960 if (pAd->CommonCfg.bWirelessEvent)
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 {
974 /* 5. init Group 2-way handshake if necessary. */
975 WPAStart2WayGroupHS(pAd, pEntry);
976
977 pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
978 RTMPModTimer(&pEntry->RetryTimer,
979 PEER_MSG3_RETRY_EXEC_INTV);
980 }
981 } while (FALSE);
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 */
993 void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
994 {
995 u8 Header802_3[14];
996 u8 TxTsc[6];
997 struct rt_eapol_packet EAPOLPKT;
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;
1003
1004 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1005
1006 if ((!pEntry) || (!pEntry->ValidAsCLI))
1007 return;
1008
1009 do {
1010 /* Increment replay counter by 1 */
1011 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1012
1013 /* Construct EAPoL message - Group Msg 1 */
1014 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
1015 ConstructEapolMsg(pEntry,
1016 group_cipher,
1017 EAPOL_GROUP_MSG_1,
1018 default_key,
1019 (u8 *) gnonce_ptr,
1020 TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT);
1021
1022 /* Make outgoing frame */
1023 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
1024 RTMPToWirelessSta(pAd, pEntry,
1025 Header802_3, LENGTH_802_3,
1026 (u8 *)& EAPOLPKT,
1027 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
1028 FALSE);
1029
1030 } while (FALSE);
1031
1032 DBGPRINT(RT_DEBUG_TRACE,
1033 ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
1034
1035 return;
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 */
1055 void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd,
1056 struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
1057 {
1058 u8 Header802_3[14];
1059 struct rt_eapol_packet EAPOLPKT;
1060 struct rt_eapol_packet * pGroup;
1061 u32 MsgLen;
1062 BOOLEAN Cancelled;
1063 u8 default_key = 0;
1064 u8 group_cipher = Ndis802_11WEPDisabled;
1065 u8 *pCurrentAddr = NULL;
1066
1067 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1068
1069 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
1070 return;
1071
1072 {
1073 pCurrentAddr = pAd->CurrentAddress;
1074 group_cipher = pAd->StaCfg.GroupCipher;
1075 default_key = pAd->StaCfg.DefaultKeyId;
1076 }
1077
1078 /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */
1079 pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1080 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
1081
1082 /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */
1083 if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry)
1084 == FALSE)
1085 return;
1086
1087 /* delete retry timer */
1088 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1089
1090 /* Save Replay counter, it will use to construct message 2 */
1091 NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter,
1092 LEN_KEY_DESC_REPLAY);
1093
1094 /* Construct EAPoL message - Group Msg 2 */
1095 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
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 */
1100 0, &EAPOLPKT);
1101
1102 /* open 802.1x port control and privacy filter */
1103 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1104 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1105
1106 STA_PORT_SECURED(pAd);
1107 /* Indicate Connected for GUI */
1108 pAd->IndicateMediaState = NdisMediaStateConnected;
1109
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)));
1115
1116 /* init header and Fill Packet and send Msg 2 to authenticator */
1117 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
1118 RTMPToWirelessSta(pAd, pEntry,
1119 Header802_3, sizeof(Header802_3),
1120 (u8 *)& EAPOLPKT,
1121 CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE);
1122
1123 DBGPRINT(RT_DEBUG_TRACE,
1124 ("<=== PeerGroupMsg1Action: sned group message 2\n"));
1125 }
1126
1127 /*
1128 ==========================================================================
1129 Description:
1130 When receiving the last packet of 2-way groupkey handshake.
1131 Return:
1132 ==========================================================================
1133 */
1134 void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd,
1135 struct rt_mac_table_entry *pEntry,
1136 void * Msg, u32 MsgLen)
1137 {
1138 u32 Len;
1139 u8 *pData;
1140 BOOLEAN Cancelled;
1141 struct rt_eapol_packet * pMsg2;
1142 u8 group_cipher = Ndis802_11WEPDisabled;
1143
1144 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1145
1146 do {
1147 if ((!pEntry) || (!pEntry->ValidAsCLI))
1148 break;
1149
1150 if (MsgLen <
1151 (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) -
1152 MAX_LEN_OF_RSNIE - 2))
1153 break;
1154
1155 if (pEntry->WpaState != AS_PTKINITDONE)
1156 break;
1157
1158 pData = (u8 *)Msg;
1159 pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H);
1160 Len = MsgLen - LENGTH_802_1_H;
1161
1162 /* Sanity Check peer group message 2 - Replay Counter, MIC */
1163 if (PeerWpaMessageSanity
1164 (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1165 break;
1166
1167 /* 3. upgrade state */
1168
1169 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1170 pEntry->GTKState = REKEY_ESTABLISHED;
1171
1172 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
1173 || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
1174 /* send wireless event - for set key done WPA2 */
1175 if (pAd->CommonCfg.bWirelessEvent)
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 {
1189 /* send wireless event - for set key done WPA */
1190 if (pAd->CommonCfg.bWirelessEvent)
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)));
1203 }
1204 } while (FALSE);
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 available
1226
1227 ========================================================================
1228 */
1229 BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType)
1230 {
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;
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:
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 length
1271
1272 Return Value:
1273 u8 *output - the calculated result
1274
1275 Note:
1276 802.11i-2004 Annex H.3
1277
1278 ========================================================================
1279 */
1280 void PRF(u8 * key,
1281 int key_len,
1282 u8 * prefix,
1283 int prefix_len,
1284 u8 * data, int data_len, u8 * output, int len)
1285 {
1286 int i;
1287 u8 *input;
1288 int currentindex = 0;
1289 int total_len;
1290
1291 /* Allocate memory for input */
1292 os_alloc_mem(NULL, (u8 **) & input, 1024);
1293
1294 if (input == NULL) {
1295 DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n"));
1296 return;
1297 }
1298 /* Generate concatenation input */
1299 NdisMoveMemory(input, prefix, prefix_len);
1300
1301 /* Concatenate a single octet containing 0 */
1302 input[prefix_len] = 0;
1303
1304 /* Concatenate specific data */
1305 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1306 total_len = prefix_len + 1 + data_len;
1307
1308 /* Concatenate a single octet containing 0 */
1309 /* This octet shall be update later */
1310 input[total_len] = 0;
1311 total_len++;
1312
1313 /* Iterate to calculate the result by hmac-sha-1 */
1314 /* Then concatenate to last result */
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;
1319
1320 /* update the last octet */
1321 input[total_len - 1]++;
1322 }
1323 os_free_mem(NULL, input);
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
1333 static void F(char *password, unsigned char *ssid, int ssidlength,
1334 int iterations, int count, unsigned char *output)
1335 {
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);
1345 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */
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) */
1352 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */
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 }
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 */
1368 int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output)
1369 {
1370 if ((strlen(password) > 63) || (ssidlength > 32))
1371 return 0;
1372
1373 F(password, ssid, ssidlength, 4096, 1, output);
1374 F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1375 return 1;
1376 }
1377
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 */
1402 void WpaDerivePTK(struct rt_rtmp_adapter *pAd,
1403 u8 * PMK,
1404 u8 * ANonce,
1405 u8 * AA,
1406 u8 * SNonce,
1407 u8 * SA, u8 * output, u32 len)
1408 {
1409 u8 concatenation[76];
1410 u32 CurrPos = 0;
1411 u8 temp[32];
1412 u8 Prefix[] =
1413 { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1414 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'
1415 };
1416
1417 /* initiate the concatenation input */
1418 NdisZeroMemory(temp, sizeof(temp));
1419 NdisZeroMemory(concatenation, 76);
1420
1421 /* Get smaller address */
1422 if (RTMPCompareMemory(SA, AA, 6) == 1)
1423 NdisMoveMemory(concatenation, AA, 6);
1424 else
1425 NdisMoveMemory(concatenation, SA, 6);
1426 CurrPos += 6;
1427
1428 /* Get larger address */
1429 if (RTMPCompareMemory(SA, AA, 6) == 1)
1430 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1431 else
1432 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1433
1434 /* store the larger mac address for backward compatible of */
1435 /* ralink proprietary STA-key issue */
1436 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
1437 CurrPos += 6;
1438
1439 /* Get smaller Nonce */
1440 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1441 NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
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
1448 /* Get larger Nonce */
1449 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1450 NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
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
1459 /* Use PRF to generate PTK */
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 */
1481 void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random)
1482 {
1483 int i, curr;
1484 u8 local[80], KeyCounter[32];
1485 u8 result[80];
1486 unsigned long CurrentTime;
1487 u8 prefix[] =
1488 { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' };
1489
1490 /* Zero the related information */
1491 NdisZeroMemory(result, 80);
1492 NdisZeroMemory(local, 80);
1493 NdisZeroMemory(KeyCounter, 32);
1494
1495 for (i = 0; i < 32; i++) {
1496 /* copy the local MAC address */
1497 COPY_MAC_ADDR(local, macAddr);
1498 curr = MAC_ADDR_LEN;
1499
1500 /* concatenate the current time */
1501 NdisGetSystemUpTime(&CurrentTime);
1502 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1503 curr += sizeof(CurrentTime);
1504
1505 /* concatenate the last result */
1506 NdisMoveMemory(&local[curr], result, 32);
1507 curr += 32;
1508
1509 /* concatenate a variable */
1510 NdisMoveMemory(&local[curr], &i, 2);
1511 curr += 2;
1512
1513 /* calculate the result */
1514 PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32);
1515 }
1516
1517 NdisMoveMemory(random, result, 32);
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 */
1540 static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd,
1541 u8 ElementID,
1542 u32 WepStatus,
1543 IN BOOLEAN bMixCipher,
1544 u8 FlexibleCipher,
1545 u8 *pRsnIe, u8 * rsn_len)
1546 {
1547 u8 PairwiseCnt;
1548
1549 *rsn_len = 0;
1550
1551 /* decide WPA2 or WPA1 */
1552 if (ElementID == Wpa2Ie) {
1553 struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe;
1554
1555 /* Assign the verson as 1 */
1556 pRsnie_cipher->version = 1;
1557
1558 switch (WepStatus) {
1559 /* TKIP mode */
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);
1565 *rsn_len = sizeof(struct rt_rsnie2);
1566 break;
1567
1568 /* AES mode */
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);
1579 *rsn_len = sizeof(struct rt_rsnie2);
1580 break;
1581
1582 /* TKIP-AES mix mode */
1583 case Ndis802_11Encryption4Enabled:
1584 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1585
1586 PairwiseCnt = 1;
1587 /* Insert WPA2 TKIP as the first pairwise cipher */
1588 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) {
1589 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1590 OUI_WPA2_TKIP, 4);
1591 /* Insert WPA2 AES as the secondary pairwise cipher */
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;
1597 }
1598 } else {
1599 /* Insert WPA2 AES as the first pairwise cipher */
1600 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1601 OUI_WPA2_CCMP, 4);
1602 }
1603
1604 pRsnie_cipher->ucount = PairwiseCnt;
1605 *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1));
1606 break;
1607 }
1608
1609 if ((pAd->OpMode == OPMODE_STA) &&
1610 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1611 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
1612 u32 GroupCipher = pAd->StaCfg.GroupCipher;
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;
1622 }
1623 }
1624 /* swap for big-endian platform */
1625 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1626 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1627 } else {
1628 struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe;
1629
1630 /* Assign OUI and version */
1631 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
1632 pRsnie_cipher->version = 1;
1633
1634 switch (WepStatus) {
1635 /* TKIP mode */
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);
1641 *rsn_len = sizeof(struct rt_rsnie);
1642 break;
1643
1644 /* AES mode */
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);
1655 *rsn_len = sizeof(struct rt_rsnie);
1656 break;
1657
1658 /* TKIP-AES mix mode */
1659 case Ndis802_11Encryption4Enabled:
1660 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1661
1662 PairwiseCnt = 1;
1663 /* Insert WPA TKIP as the first pairwise cipher */
1664 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) {
1665 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1666 OUI_WPA_TKIP, 4);
1667 /* Insert WPA AES as the secondary pairwise cipher */
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;
1673 }
1674 } else {
1675 /* Insert WPA AES as the first pairwise cipher */
1676 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1677 OUI_WPA_CCMP, 4);
1678 }
1679
1680 pRsnie_cipher->ucount = PairwiseCnt;
1681 *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1));
1682 break;
1683 }
1684
1685 if ((pAd->OpMode == OPMODE_STA) &&
1686 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1687 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
1688 u32 GroupCipher = pAd->StaCfg.GroupCipher;
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;
1698 }
1699 }
1700 /* swap for big-endian platform */
1701 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1702 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
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 */
1725 static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd,
1726 u8 ElementID,
1727 u32 AuthMode,
1728 u8 apidx,
1729 u8 *pRsnIe, u8 * rsn_len)
1730 {
1731 struct rt_rsnie_auth *pRsnie_auth;
1732 u8 AkmCnt = 1; /* default as 1 */
1733
1734 pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len));
1735
1736 /* decide WPA2 or WPA1 */
1737 if (ElementID == Wpa2Ie) {
1738
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;
1745
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 }
1778 }
1779
1780 pRsnie_auth->acount = AkmCnt;
1781 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1782
1783 /* update current RSNIE length */
1784 (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1)));
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 */
1806 static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd,
1807 u8 ElementID,
1808 u8 apidx,
1809 u8 *pRsnIe, u8 * rsn_len)
1810 {
1811 RSN_CAPABILITIES *pRSN_Cap;
1812
1813 /* it could be ignored in WPA1 mode */
1814 if (ElementID == WpaIe)
1815 return;
1816
1817 pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len));
1818
1819 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1820
1821 (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */
1822
1823 }
1824
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 */
1843 void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd,
1844 u32 AuthMode, u32 WepStatus, u8 apidx)
1845 {
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;
1850 BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */
1851 u8 p_offset;
1852 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */
1853
1854 rsnielen_cur_p = NULL;
1855 rsnielen_ex_cur_p = NULL;
1856
1857 {
1858 {
1859 if (pAd->StaCfg.WpaSupplicantUP !=
1860 WPA_SUPPLICANT_DISABLE) {
1861 if (AuthMode < Ndis802_11AuthModeWPA)
1862 return;
1863 } else {
1864 /* Support WPAPSK or WPA2PSK in STA-Infra mode */
1865 /* Support WPANone in STA-Adhoc mode */
1866 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
1867 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
1868 (AuthMode != Ndis802_11AuthModeWPANone)
1869 )
1870 return;
1871 }
1872
1873 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n"));
1874
1875 /* Zero RSNIE context */
1876 pAd->StaCfg.RSNIE_Len = 0;
1877 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1878
1879 /* Pointer to RSNIE */
1880 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1881 pRsnIe = pAd->StaCfg.RSN_IE;
1882
1883 bMixCipher = pAd->StaCfg.bMixCipher;
1884 }
1885 }
1886
1887 /* indicate primary RSNIE as WPA or WPA2 */
1888 if ((AuthMode == Ndis802_11AuthModeWPA) ||
1889 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
1890 (AuthMode == Ndis802_11AuthModeWPANone) ||
1891 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
1892 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
1893 PrimaryRsnie = WpaIe;
1894 else
1895 PrimaryRsnie = Wpa2Ie;
1896
1897 {
1898 /* Build the primary RSNIE */
1899 /* 1. insert cipher suite */
1900 RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher,
1901 FlexibleCipher, pRsnIe, &p_offset);
1902
1903 /* 2. insert AKM */
1904 RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe,
1905 &p_offset);
1906
1907 /* 3. insert capability */
1908 RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
1909 }
1910
1911 /* 4. update the RSNIE length */
1912 *rsnielen_cur_p = p_offset;
1913
1914 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1915
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 */
1935 BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd,
1936 struct rt_mac_table_entry *pEntry,
1937 u8 *pData,
1938 unsigned long DataByteCount, u8 FromWhichBSSID)
1939 {
1940 unsigned long Body_len;
1941 BOOLEAN Cancelled;
1942
1943 if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
1944 return FALSE;
1945
1946 /* Skip LLC header */
1947 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
1948 /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */
1949 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) {
1950 pData += 6;
1951 }
1952 /* Skip 2-bytes EAPoL type */
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;
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 */
2017 char *GetEapolMsgType(char msg)
2018 {
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";
2033 }
2034
2035 /*
2036 ========================================================================
2037
2038 Routine Description:
2039 Check Sanity RSN IE of EAPoL message
2040
2041 Arguments:
2042
2043 Return Value:
2044
2045 ========================================================================
2046 */
2047 BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd,
2048 u8 *pData,
2049 u8 DataLen,
2050 struct rt_mac_table_entry *pEntry, u8 * Offset)
2051 {
2052 u8 *pVIE;
2053 u8 len;
2054 struct rt_eid * pEid;
2055 BOOLEAN result = FALSE;
2056
2057 pVIE = pData;
2058 len = DataLen;
2059 *Offset = 0;
2060
2061 while (len > sizeof(struct rt_rsnie2)) {
2062 pEid = (struct rt_eid *) pVIE;
2063 /* WPA RSN IE */
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;
2073 }
2074
2075 *Offset += (pEid->Len + 2);
2076 }
2077 /* WPA2 RSN IE */
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;
2090 }
2091
2092 *Offset += (pEid->Len + 2);
2093 } else {
2094 break;
2095 }
2096
2097 pVIE += (pEid->Len + 2);
2098 len -= (pEid->Len + 2);
2099 }
2100
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 */
2121 BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd,
2122 u8 *pKeyData,
2123 u8 KeyDataLen,
2124 u8 GroupKeyIndex,
2125 u8 MsgType,
2126 IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry)
2127 {
2128 struct rt_kde_encap * pKDE = NULL;
2129 u8 *pMyKeyData = pKeyData;
2130 u8 KeyDataLength = KeyDataLen;
2131 u8 GTKLEN = 0;
2132 u8 DefaultIdx = 0;
2133 u8 skip_offset;
2134
2135 /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */
2136 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) {
2137 /* Check RSN IE whether it is WPA2/WPA2PSK */
2138 if (!RTMPCheckRSNIE
2139 (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) {
2140 /* send wireless event - for RSN IE different */
2141 if (pAd->CommonCfg.bWirelessEvent)
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));
2150 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
2151 hex_dump("Desired RSN_IE ", pEntry->RSN_IE,
2152 pEntry->RSNIE_Len);
2153
2154 return FALSE;
2155 } else {
2156 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) {
2157 WpaShowAllsuite(pMyKeyData, skip_offset);
2158
2159 /* skip RSN IE */
2160 pMyKeyData += skip_offset;
2161 KeyDataLength -= skip_offset;
2162 DBGPRINT(RT_DEBUG_TRACE,
2163 ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n",
2164 skip_offset));
2165 } else
2166 return TRUE;
2167 }
2168 }
2169
2170 DBGPRINT(RT_DEBUG_TRACE,
2171 ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n",
2172 KeyDataLength));
2173 /*hex_dump("remain data", pMyKeyData, KeyDataLength); */
2174
2175 /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */
2176 if (bWPA2
2177 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) {
2178 if (KeyDataLength >= 8) /* KDE format exclude GTK length */
2179 {
2180 pKDE = (struct rt_kde_encap *) pMyKeyData;
2181
2182 DefaultIdx = pKDE->GTKEncap.Kid;
2183
2184 /* Sanity check - KED length */
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 }
2190 /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */
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;
2197 }
2198
2199 } else {
2200 DBGPRINT(RT_DEBUG_ERROR,
2201 ("ERROR: KDE format length is too short \n"));
2202 return FALSE;
2203 }
2204
2205 DBGPRINT(RT_DEBUG_TRACE,
2206 ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n",
2207 DefaultIdx, GTKLEN));
2208 /* skip it */
2209 pMyKeyData += 8;
2210 KeyDataLength -= 8;
2211
2212 } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) {
2213 DefaultIdx = GroupKeyIndex;
2214 DBGPRINT(RT_DEBUG_TRACE,
2215 ("GTK DefaultKeyID=%d \n", DefaultIdx));
2216 }
2217 /* Sanity check - shared key index must be 1 ~ 3 */
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;
2224 }
2225
2226 {
2227 struct rt_cipher_key *pSharedKey;
2228
2229 /* set key material, TxMic and RxMic */
2230 NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2231 pAd->StaCfg.DefaultKeyId = DefaultIdx;
2232
2233 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
2234
2235 /* Prepare pair-wise key information into shared key table */
2236 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
2237 pSharedKey->KeyLen = LEN_TKIP_EK;
2238 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
2239 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
2240 LEN_TKIP_RXMICK);
2241 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
2242 LEN_TKIP_TXMICK);
2243
2244 /* Update Shared Key CipherAlg */
2245 pSharedKey->CipherAlg = CIPHER_NONE;
2246 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
2247 pSharedKey->CipherAlg = CIPHER_TKIP;
2248 else if (pAd->StaCfg.GroupCipher ==
2249 Ndis802_11Encryption3Enabled)
2250 pSharedKey->CipherAlg = CIPHER_AES;
2251 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
2252 pSharedKey->CipherAlg = CIPHER_WEP64;
2253 else if (pAd->StaCfg.GroupCipher ==
2254 Ndis802_11GroupWEP104Enabled)
2255 pSharedKey->CipherAlg = CIPHER_WEP128;
2256
2257 /* Update group key information to ASIC Shared Key Table */
2258 AsicAddSharedKeyEntry(pAd,
2259 BSS0,
2260 pAd->StaCfg.DefaultKeyId,
2261 pSharedKey->CipherAlg,
2262 pSharedKey->Key,
2263 pSharedKey->TxMic, pSharedKey->RxMic);
2264
2265 /* Update ASIC WCID attribute table and IVEIV table */
2266 RTMPAddWcidAttributeEntry(pAd,
2267 BSS0,
2268 pAd->StaCfg.DefaultKeyId,
2269 pSharedKey->CipherAlg, NULL);
2270 }
2271
2272 return TRUE;
2273
2274 }
2275
2276 /*
2277 ========================================================================
2278
2279 Routine Description:
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
2313 Arguments:
2314 pAd Pointer to our adapter
2315
2316 Return Value:
2317 None
2318
2319 Note:
2320
2321 ========================================================================
2322 */
2323 void ConstructEapolMsg(struct rt_mac_table_entry *pEntry,
2324 u8 GroupKeyWepStatus,
2325 u8 MsgType,
2326 u8 DefaultKeyIdx,
2327 u8 * KeyNonce,
2328 u8 * TxRSC,
2329 u8 * GTK,
2330 u8 * RSNIE,
2331 u8 RSNIE_Len, struct rt_eapol_packet * pMsg)
2332 {
2333 BOOLEAN bWPA2 = FALSE;
2334 u8 KeyDescVer;
2335
2336 /* Choose WPA2 or not */
2337 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2338 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2339 bWPA2 = TRUE;
2340
2341 /* Init Packet and Fill header */
2342 pMsg->ProVer = EAPOL_VER;
2343 pMsg->ProType = EAPOLKey;
2344
2345 /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */
2346 SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
2347
2348 /* Fill in EAPoL descriptor */
2349 if (bWPA2)
2350 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2351 else
2352 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
2353
2354 /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */
2355 {
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. */
2358 KeyDescVer =
2359 (((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
2360 || (GroupKeyWepStatus ==
2361 Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES)
2362 : (DESC_TYPE_TKIP));
2363 }
2364
2365 pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2366
2367 /* Specify Key Type as Group(0) or Pairwise(1) */
2368 if (MsgType >= EAPOL_GROUP_MSG_1)
2369 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
2370 else
2371 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
2372
2373 /* Specify Key Index, only group_msg1_WPA1 */
2374 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2375 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
2376
2377 if (MsgType == EAPOL_PAIR_MSG_3)
2378 pMsg->KeyDesc.KeyInfo.Install = 1;
2379
2380 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)
2381 || (MsgType == EAPOL_GROUP_MSG_1))
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)) ||
2388 (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) {
2389 pMsg->KeyDesc.KeyInfo.Secure = 1;
2390 }
2391
2392 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
2393 (MsgType == EAPOL_GROUP_MSG_1))) {
2394 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2395 }
2396 /* key Information element has done. */
2397 *(u16 *) (&pMsg->KeyDesc.KeyInfo) =
2398 cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo));
2399
2400 /* Fill in Key Length */
2401 {
2402 if (MsgType >= EAPOL_GROUP_MSG_1) {
2403 /* the length of group key cipher */
2404 pMsg->KeyDesc.KeyLength[1] =
2405 ((GroupKeyWepStatus ==
2406 Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH :
2407 LEN_AES_KEY);
2408 } else {
2409 /* the length of pairwise key cipher */
2410 pMsg->KeyDesc.KeyLength[1] =
2411 ((pEntry->WepStatus ==
2412 Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY :
2413 LEN_AES_KEY);
2414 }
2415 }
2416
2417 /* Fill in replay counter */
2418 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter,
2419 LEN_KEY_DESC_REPLAY);
2420
2421 /* Fill Key Nonce field */
2422 /* ANonce : pairwise_msg1 & pairwise_msg3 */
2423 /* SNonce : pairwise_msg2 */
2424 /* GNonce : group_msg1_wpa1 */
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);
2429
2430 /* Fill key IV - WPA2 as 0, WPA1 as random */
2431 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) {
2432 /* Suggest IV be random number plus some number, */
2433 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16],
2434 LEN_KEY_DESC_IV);
2435 pMsg->KeyDesc.KeyIv[15] += 2;
2436 }
2437 /* Fill Key RSC field */
2438 /* It contains the RSC for the GTK being installed. */
2439 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2)
2440 || (MsgType == EAPOL_GROUP_MSG_1)) {
2441 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2442 }
2443 /* Clear Key MIC field for MIC calculation later */
2444 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
2445
2446 ConstructEapolKeyData(pEntry,
2447 GroupKeyWepStatus,
2448 KeyDescVer,
2449 MsgType,
2450 DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg);
2451
2452 /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */
2453 if (MsgType != EAPOL_PAIR_MSG_1) {
2454 CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
2455 }
2456
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",
2462 CONV_ARRARY_TO_u16(pMsg->Body_Len)));
2463 DBGPRINT(RT_DEBUG_TRACE,
2464 (" Key length = %d \n",
2465 CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength)));
2466
2467 }
2468
2469 /*
2470 ========================================================================
2471
2472 Routine Description:
2473 Construct the Key Data field of EAPoL message
2474
2475 Arguments:
2476 pAd Pointer to our adapter
2477 Elem Message body
2478
2479 Return Value:
2480 None
2481
2482 Note:
2483
2484 ========================================================================
2485 */
2486 void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
2487 u8 GroupKeyWepStatus,
2488 u8 keyDescVer,
2489 u8 MsgType,
2490 u8 DefaultKeyIdx,
2491 u8 * GTK,
2492 u8 * RSNIE,
2493 u8 RSNIE_LEN, struct rt_eapol_packet * pMsg)
2494 {
2495 u8 *mpool, *Key_Data, *Rc4GTK;
2496 u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)];
2497 unsigned long data_offset;
2498 BOOLEAN bWPA2Capable = FALSE;
2499 struct rt_rtmp_adapter *pAd = pEntry->pAd;
2500 BOOLEAN GTK_Included = FALSE;
2501
2502 /* Choose WPA2 or not */
2503 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2504 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2505 bWPA2Capable = TRUE;
2506
2507 if (MsgType == EAPOL_PAIR_MSG_1 ||
2508 MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
2509 return;
2510
2511 /* allocate memory pool */
2512 os_alloc_mem(NULL, (u8 **) & mpool, 1500);
2513
2514 if (mpool == NULL)
2515 return;
2516
2517 /* Rc4GTK Len = 512 */
2518 Rc4GTK = (u8 *) ROUND_UP(mpool, 4);
2519 /* Key_Data Len = 512 */
2520 Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4);
2521
2522 NdisZeroMemory(Key_Data, 512);
2523 SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
2524 data_offset = 0;
2525
2526 /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */
2527 if (RSNIE_LEN
2528 && ((MsgType == EAPOL_PAIR_MSG_2)
2529 || (MsgType == EAPOL_PAIR_MSG_3))) {
2530 u8 *pmkid_ptr = NULL;
2531 u8 pmkid_len = 0;
2532
2533 RTMPInsertRSNIE(&Key_Data[data_offset],
2534 &data_offset,
2535 RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len);
2536 }
2537
2538 /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */
2539 if (bWPA2Capable
2540 && ((MsgType == EAPOL_PAIR_MSG_3)
2541 || (MsgType == EAPOL_GROUP_MSG_1))) {
2542 /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */
2543 Key_Data[data_offset + 0] = 0xDD;
2544
2545 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
2546 Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */
2547 } else {
2548 Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */
2549 }
2550
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;
2555
2556 /* GTK KDE format - 802.11i-2004 Figure-43x */
2557 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
2558 Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */
2559
2560 data_offset += 8;
2561 }
2562
2563 /* Encapsulate GTK */
2564 /* Only for pairwise_msg3_WPA2 and group_msg1 */
2565 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
2566 || (MsgType == EAPOL_GROUP_MSG_1)) {
2567 /* Fill in GTK */
2568 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
2569 NdisMoveMemory(&Key_Data[data_offset], GTK,
2570 LEN_AES_KEY);
2571 data_offset += LEN_AES_KEY;
2572 } else {
2573 NdisMoveMemory(&Key_Data[data_offset], GTK,
2574 TKIP_GTK_LENGTH);
2575 data_offset += TKIP_GTK_LENGTH;
2576 }
2577
2578 GTK_Included = TRUE;
2579 }
2580
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 */
2583 if (GTK_Included) {
2584 /*hex_dump("GTK_Included", Key_Data, data_offset); */
2585
2586 if ((keyDescVer == DESC_TYPE_AES)) {
2587 u8 remainder = 0;
2588 u8 pad_len = 0;
2589
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. */
2593
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. */
2598 if ((remainder = data_offset & 0x07) != 0) {
2599 int i;
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;
2607 }
2608
2609 AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data,
2610 data_offset, Rc4GTK);
2611 /* AES wrap function will grow 8 bytes in length */
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. */
2616
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. */
2620
2621 /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */
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);
2626 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */
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);
2632 }
2633
2634 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
2635 } else {
2636 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
2637 }
2638
2639 /* Update key data length field and total body length */
2640 SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
2641 INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset);
2642
2643 os_free_mem(NULL, mpool);
2644
2645 }
2646
2647 /*
2648 ========================================================================
2649
2650 Routine Description:
2651 Calcaulate MIC. It is used during 4-ways handsharking.
2652
2653 Arguments:
2654 pAd - pointer to our pAdapter context
2655 PeerWepStatus - indicate the encryption type
2656
2657 Return Value:
2658
2659 Note:
2660
2661 ========================================================================
2662 */
2663 static void CalculateMIC(u8 KeyDescVer,
2664 u8 * PTK, struct rt_eapol_packet * pMsg)
2665 {
2666 u8 *OutBuffer;
2667 unsigned long FrameLen = 0;
2668 u8 mic[LEN_KEY_DESC_MIC];
2669 u8 digest[80];
2670
2671 /* allocate memory for MIC calculation */
2672 os_alloc_mem(NULL, (u8 **) & OutBuffer, 512);
2673
2674 if (OutBuffer == NULL) {
2675 DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n"));
2676 return;
2677 }
2678 /* make a frame for calculating MIC. */
2679 MakeOutgoingFrame(OutBuffer, &FrameLen,
2680 CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg,
2681 END_OF_ARGS);
2682
2683 NdisZeroMemory(mic, sizeof(mic));
2684
2685 /* Calculate MIC */
2686 if (KeyDescVer == DESC_TYPE_AES) {
2687 HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest,
2688 SHA1_DIGEST_SIZE);
2689 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
2690 } else {
2691 HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic,
2692 MD5_DIGEST_SIZE);
2693 }
2694
2695 /* store the calculated MIC */
2696 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
2697
2698 os_free_mem(NULL, OutBuffer);
2699 }
2700
2701 /*
2702 ========================================================================
2703
2704 Routine Description:
2705 Some received frames can't decrypt by Asic, so decrypt them by software.
2706
2707 Arguments:
2708 pAd - pointer to our pAdapter context
2709 PeerWepStatus - indicate the encryption type
2710
2711 Return Value:
2712 NDIS_STATUS_SUCCESS - decryption successful
2713 NDIS_STATUS_FAILURE - decryption failure
2714
2715 ========================================================================
2716 */
2717 int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd,
2718 struct rt_rx_blk *pRxBlk,
2719 IN NDIS_802_11_ENCRYPTION_STATUS
2720 GroupCipher, struct rt_cipher_key *pShard_key)
2721 {
2722 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
2723
2724 /* handle WEP decryption */
2725 if (GroupCipher == Ndis802_11Encryption1Enabled) {
2726 if (RTMPSoftDecryptWEP
2727 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2728 pShard_key)) {
2729
2730 /*Minus IV[4] & ICV[4] */
2731 pRxWI->MPDUtotalByteCount -= 8;
2732 } else {
2733 DBGPRINT(RT_DEBUG_ERROR,
2734 ("ERROR : Software decrypt WEP data fails.\n"));
2735 /* give up this frame */
2736 return NDIS_STATUS_FAILURE;
2737 }
2738 }
2739 /* handle TKIP decryption */
2740 else if (GroupCipher == Ndis802_11Encryption2Enabled) {
2741 if (RTMPSoftDecryptTKIP
2742 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0,
2743 pShard_key)) {
2744
2745 /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */
2746 pRxWI->MPDUtotalByteCount -= 20;
2747 } else {
2748 DBGPRINT(RT_DEBUG_ERROR,
2749 ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
2750 /* give up this frame */
2751 return NDIS_STATUS_FAILURE;
2752 }
2753 }
2754 /* handle AES decryption */
2755 else if (GroupCipher == Ndis802_11Encryption3Enabled) {
2756 if (RTMPSoftDecryptAES
2757 (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2758 pShard_key)) {
2759
2760 /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */
2761 pRxWI->MPDUtotalByteCount -= 16;
2762 } else {
2763 DBGPRINT(RT_DEBUG_ERROR,
2764 ("ERROR : RTMPSoftDecryptAES Failed\n"));
2765 /* give up this frame */
2766 return NDIS_STATUS_FAILURE;
2767 }
2768 } else {
2769 /* give up this frame */
2770 return NDIS_STATUS_FAILURE;
2771 }
2772
2773 return NDIS_STATUS_SUCCESS;
2774
2775 }
2776
2777 u8 *GetSuiteFromRSNIE(u8 *rsnie,
2778 u32 rsnie_len, u8 type, u8 * count)
2779 {
2780 struct rt_eid * pEid;
2781 int len;
2782 u8 *pBuf;
2783 int offset = 0;
2784 struct rt_rsnie_auth *pAkm;
2785 u16 acount;
2786 BOOLEAN isWPA2 = FALSE;
2787
2788 pEid = (struct rt_eid *) rsnie;
2789 len = rsnie_len - 2; /* exclude IE and length */
2790 pBuf = (u8 *)& pEid->Octet[0];
2791
2792 /* set default value */
2793 *count = 0;
2794
2795 /* Check length */
2796 if ((len <= 0) || (pEid->Len != len)) {
2797 DBGPRINT_ERR("%s : The length is invalid\n", __func__);
2798 return NULL;
2799 }
2800 /* Check WPA or WPA2 */
2801 if (pEid->Eid == IE_WPA) {
2802 struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf;
2803 u16 ucount;
2804
2805 if (len < sizeof(struct rt_rsnie)) {
2806 DBGPRINT_ERR("%s : The length is too short for WPA\n", __func__);
2807 return NULL;
2808 }
2809 /* Get the count of pairwise cipher */
2810 ucount = cpu2le16(pRsnie->ucount);
2811 if (ucount > 2) {
2812 DBGPRINT_ERR("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount);
2813 return NULL;
2814 }
2815 /* Get the group cipher */
2816 if (type == GROUP_SUITE) {
2817 *count = 1;
2818 return pRsnie->mcast;
2819 }
2820 /* Get the pairwise cipher suite */
2821 else if (type == PAIRWISE_SUITE) {
2822 DBGPRINT(RT_DEBUG_TRACE,
2823 ("%s : The count of pairwise cipher is %d\n",
2824 __func__, ucount));
2825 *count = ucount;
2826 return pRsnie->ucast[0].oui;
2827 }
2828
2829 offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1));
2830
2831 } else if (pEid->Eid == IE_RSN) {
2832 struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf;
2833 u16 ucount;
2834
2835 isWPA2 = TRUE;
2836
2837 if (len < sizeof(struct rt_rsnie2)) {
2838 DBGPRINT_ERR("%s : The length is too short for WPA2\n", __func__);
2839 return NULL;
2840 }
2841 /* Get the count of pairwise cipher */
2842 ucount = cpu2le16(pRsnie->ucount);
2843 if (ucount > 2) {
2844 DBGPRINT_ERR("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount);
2845 return NULL;
2846 }
2847 /* Get the group cipher */
2848 if (type == GROUP_SUITE) {
2849 *count = 1;
2850 return pRsnie->mcast;
2851 }
2852 /* Get the pairwise cipher suite */
2853 else if (type == PAIRWISE_SUITE) {
2854 DBGPRINT(RT_DEBUG_TRACE,
2855 ("%s : The count of pairwise cipher is %d\n",
2856 __func__, ucount));
2857 *count = ucount;
2858 return pRsnie->ucast[0].oui;
2859 }
2860
2861 offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1));
2862
2863 } else {
2864 DBGPRINT_ERR("%s : Unknown IE (%d)\n", __func__, pEid->Eid);
2865 return NULL;
2866 }
2867
2868 /* skip group cipher and pairwise cipher suite */
2869 pBuf += offset;
2870 len -= offset;
2871
2872 if (len < sizeof(struct rt_rsnie_auth)) {
2873 DBGPRINT_ERR("%s : The length of RSNIE is too short\n", __func__);
2874 return NULL;
2875 }
2876 /* pointer to AKM count */
2877 pAkm = (struct rt_rsnie_auth *)pBuf;
2878
2879 /* Get the count of pairwise cipher */
2880 acount = cpu2le16(pAkm->acount);
2881 if (acount > 2) {
2882 DBGPRINT_ERR("%s : The count(%d) of AKM is invlaid\n", __func__, acount);
2883 return NULL;
2884 }
2885 /* Get the AKM suite */
2886 if (type == AKM_SUITE) {
2887 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
2888 __func__, acount));
2889 *count = acount;
2890 return pAkm->auth[0].oui;
2891 }
2892 offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1));
2893
2894 pBuf += offset;
2895 len -= offset;
2896
2897 /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */
2898 if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) {
2899 /* Skip RSN capability and PMKID-Count */
2900 pBuf += (sizeof(RSN_CAPABILITIES) + 2);
2901 len -= (sizeof(RSN_CAPABILITIES) + 2);
2902
2903 /* Get PMKID */
2904 if (type == PMKID_LIST) {
2905 *count = 1;
2906 return pBuf;
2907 }
2908 } else {
2909 DBGPRINT_ERR("%s : it can't get any more information beyond AKM \n", __func__);
2910 return NULL;
2911 }
2912
2913 *count = 0;
2914 /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */
2915 return NULL;
2916
2917 }
2918
2919 void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len)
2920 {
2921 u8 *pSuite = NULL;
2922 u8 count;
2923
2924 hex_dump("RSNIE", rsnie, rsnie_len);
2925
2926 /* group cipher */
2927 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count);
2928 if (pSuite != NULL) {
2929 hex_dump("group cipher", pSuite, 4 * count);
2930 }
2931 /* pairwise cipher */
2932 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count);
2933 if (pSuite != NULL) {
2934 hex_dump("pairwise cipher", pSuite, 4 * count);
2935 }
2936 /* AKM */
2937 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count);
2938 if (pSuite != NULL) {
2939 hex_dump("AKM suite", pSuite, 4 * count);
2940 }
2941 /* PMKID */
2942 pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count);
2943 if (pSuite != NULL) {
2944 hex_dump("PMKID", pSuite, LEN_PMKID);
2945 }
2946
2947 }
2948
2949 void RTMPInsertRSNIE(u8 *pFrameBuf,
2950 unsigned long *pFrameLen,
2951 u8 *rsnie_ptr,
2952 u8 rsnie_len,
2953 u8 *pmkid_ptr, u8 pmkid_len)
2954 {
2955 u8 *pTmpBuf;
2956 unsigned long TempLen = 0;
2957 u8 extra_len = 0;
2958 u16 pmk_count = 0;
2959 u8 ie_num;
2960 u8 total_len = 0;
2961 u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC };
2962
2963 pTmpBuf = pFrameBuf;
2964
2965 /* PMKID-List Must larger than 0 and the multiple of 16. */
2966 if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) {
2967 extra_len = sizeof(u16)+ pmkid_len;
2968
2969 pmk_count = (pmkid_len >> 4);
2970 pmk_count = cpu2le16(pmk_count);
2971 } else {
2972 DBGPRINT(RT_DEBUG_WARN,
2973 ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
2974 __func__, pmkid_len));
2975 }
2976
2977 if (rsnie_len != 0) {
2978 ie_num = IE_WPA;
2979 total_len = rsnie_len;
2980
2981 if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) {
2982 ie_num = IE_RSN;
2983 total_len += extra_len;
2984 }
2985
2986 /* construct RSNIE body */
2987 MakeOutgoingFrame(pTmpBuf, &TempLen,
2988 1, &ie_num,
2989 1, &total_len,
2990 rsnie_len, rsnie_ptr, END_OF_ARGS);
2991
2992 pTmpBuf += TempLen;
2993 *pFrameLen = *pFrameLen + TempLen;
2994
2995 if (ie_num == IE_RSN) {
2996 /* Insert PMKID-List field */
2997 if (extra_len > 0) {
2998 MakeOutgoingFrame(pTmpBuf, &TempLen,
2999 2, &pmk_count,
3000 pmkid_len, pmkid_ptr,
3001 END_OF_ARGS);
3002
3003 pTmpBuf += TempLen;
3004 *pFrameLen = *pFrameLen + TempLen;
3005 }
3006 }
3007 }
3008
3009 return;
3010 }