MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / net / wireless / rtlink / Module / wpa.c
blob0c49935bb82f2c7aa89a60e980214c204a878449
1 /*************************************************************************
2 * Ralink Tech Inc. *
3 * 4F, No. 2 Technology 5th Rd. *
4 * Science-based Industrial Park *
5 * Hsin-chu, Taiwan, R.O.C. *
6 * *
7 * (c) Copyright 2002, Ralink Technology, Inc. *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program; if not, write to the *
21 * Free Software Foundation, Inc., *
22 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23 * *
24 ************************************************************************
26 Module Name:
27 wpa.c
29 Abstract:
31 Revision History:
32 Who When What
33 -------- ---------- ----------------------------------------------
34 Jan Lee 03-07-22 Initial
35 Paul Lin 03-11-28 Modify for supplicant
37 #include "rt_config.h"
39 UCHAR CipherWpaPskTkip[] = {
40 0xDD, 0x16, // RSN IE
41 0x00, 0x50, 0xf2, 0x01, // oui
42 0x01, 0x00, // Version
43 0x00, 0x50, 0xf2, 0x02, // Multicast
44 0x01, 0x00, // Number of unicast
45 0x00, 0x50, 0xf2, 0x02, // unicast
46 0x01, 0x00, // number of authentication method
47 0x00, 0x50, 0xf2, 0x02 // authentication
49 UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR));
51 UCHAR CipherWpaPskAes[] = {
52 0xDD, 0x16, // RSN IE
53 0x00, 0x50, 0xf2, 0x01, // oui
54 0x01, 0x00, // Version
55 0x00, 0x50, 0xf2, 0x04, // Multicast
56 0x01, 0x00, // Number of unicast
57 0x00, 0x50, 0xf2, 0x04, // unicast
58 0x01, 0x00, // number of authentication method
59 0x00, 0x50, 0xf2, 0x02 // authentication
61 UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR));
64 ========================================================================
66 Routine Description:
67 Classify WPA EAP message type
69 Arguments:
70 EAPType Value of EAP message type
71 MsgType Internal Message definition for MLME state machine
73 Return Value:
74 TRUE Found appropriate message type
75 FALSE No appropriate message type
77 Note:
78 All these constants are defined in wpa.h
79 For supplicant, there is only EAPOL Key message avaliable
81 ========================================================================
83 BOOLEAN WpaMsgTypeSubst(
84 IN UCHAR EAPType,
85 OUT ULONG *MsgType)
87 switch (EAPType)
89 case EAPPacket:
90 *MsgType = EAP_MSG_TYPE_EAPPacket;
91 break;
92 case EAPOLStart:
93 *MsgType = EAP_MSG_TYPE_EAPOLStart;
94 break;
95 case EAPOLLogoff:
96 *MsgType = EAP_MSG_TYPE_EAPOLLogoff;
97 break;
98 case EAPOLKey:
99 *MsgType = EAP_MSG_TYPE_EAPOLKey;
100 break;
101 case EAPOLASFAlert:
102 *MsgType = EAP_MSG_TYPE_EAPOLASFAlert;
103 break;
104 default:
105 DBGPRINT(RT_DEBUG_INFO, "WpaMsgTypeSubst : return FALSE; \n");
106 return FALSE;
108 return TRUE;
112 ==========================================================================
113 Description:
114 association state machine init, including state transition and timer init
115 Parameters:
116 S - pointer to the association state machine
117 ==========================================================================
119 VOID WpaPskStateMachineInit(
120 IN PRTMP_ADAPTER pAd,
121 IN STATE_MACHINE *S,
122 OUT STATE_MACHINE_FUNC Trans[])
124 StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE);
125 StateMachineSetAction(S, WPA_PSK_IDLE, EAP_MSG_TYPE_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
129 ==========================================================================
130 Description:
131 This is state machine function.
132 When receiving EAPOL packets which is for 802.1x key management.
133 Use both in WPA, and WPAPSK case.
134 In this function, further dispatch to different functions according to the received packet. 3 categories are :
135 1. normal 4-way pairwisekey and 2-way groupkey handshake
136 2. MIC error (Countermeasures attack) report packet from STA.
137 3. Request for pairwise/group key update from STA
138 Return:
139 ==========================================================================
141 VOID WpaEAPOLKeyAction(
142 IN PRTMP_ADAPTER pAdapter,
143 IN MLME_QUEUE_ELEM *Elem)
145 INT MsgType;
146 UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
147 PKEY_DESCRIPTER pKeyDesc;
149 DBGPRINT(RT_DEBUG_TRACE, "-----> WpaEAPOLKeyAction\n");
150 // Get 802.11 header first
151 pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)];
153 #ifdef BIG_ENDIAN
154 *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
155 #endif
156 // Sanity check, this should only happen in WPA-PSK mode
157 if (pAdapter->PortCfg.AuthMode != Ndis802_11AuthModeWPAPSK)
158 return;
160 // 0. Debug print all bit information
161 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Description Version %d\n", pKeyDesc->KeyInfo.KeyDescVer);
162 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Type %d\n", pKeyDesc->KeyInfo.KeyType);
163 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Index %d\n", pKeyDesc->KeyInfo.KeyIndex);
164 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Install %d\n", pKeyDesc->KeyInfo.Install);
165 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Ack %d\n", pKeyDesc->KeyInfo.KeyAck);
166 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key MIC %d\n", pKeyDesc->KeyInfo.KeyMic);
167 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Secure %d\n", pKeyDesc->KeyInfo.Secure);
168 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Error %d\n", pKeyDesc->KeyInfo.Error);
169 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Request %d\n", pKeyDesc->KeyInfo.Request);
170 DBGPRINT(RT_DEBUG_INFO, "KeyInfo DL %d\n", pKeyDesc->KeyInfo.DL);
172 // 1. Check EAPOL frame version and type
173 if ((Elem->Msg[LENGTH_802_11+LENGTH_802_1_H] != EAPOL_VER) || (pKeyDesc->Type != RSN_KEY_DESC))
175 DBGPRINT(RT_DEBUG_ERROR, " Key descripter does not match with WPA rule \n");
176 return;
179 // 2.Check Version for AES & TKIP
180 if ((pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled) && (pKeyDesc->KeyInfo.KeyDescVer != DESC_TYPE_AES))
182 DBGPRINT(RT_DEBUG_ERROR, " Key descripter version not match AES \n");
183 return;
185 else if ((pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) && (pKeyDesc->KeyInfo.KeyDescVer != DESC_TYPE_TKIP))
187 DBGPRINT(RT_DEBUG_ERROR, " Key descripter version not match TKIP \n");
188 return;
191 // First validate replay counter, only accept message with larger replay counter
192 // Let equal pass, some AP start with all zero replay counter
193 NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
194 if ((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
195 (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
196 return;
198 // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant
199 MsgType = EAPOL_MSG_INVALID;
200 if ((pKeyDesc->KeyInfo.KeyType == 1) &&
201 (pKeyDesc->KeyInfo.KeyIndex == 0) &&
202 (pKeyDesc->KeyInfo.KeyAck == 1) &&
203 (pKeyDesc->KeyInfo.KeyMic == 0) &&
204 (pKeyDesc->KeyInfo.Secure == 0) &&
205 (pKeyDesc->KeyInfo.Error == 0) &&
206 (pKeyDesc->KeyInfo.Request == 0))
208 MsgType = EAPOL_PAIR_MSG_1;
209 DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Pairwise Message 1\n");
211 else if ((pKeyDesc->KeyInfo.KeyType == 1) &&
212 (pKeyDesc->KeyInfo.KeyIndex == 0) &&
213 (pKeyDesc->KeyInfo.KeyAck == 1) &&
214 (pKeyDesc->KeyInfo.KeyMic == 1) &&
215 (pKeyDesc->KeyInfo.Secure == 0) &&
216 (pKeyDesc->KeyInfo.Error == 0) &&
217 (pKeyDesc->KeyInfo.Request == 0))
219 MsgType = EAPOL_PAIR_MSG_3;
220 DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Pairwise Message 3\n");
222 else if ((pKeyDesc->KeyInfo.KeyType == 0) &&
223 (pKeyDesc->KeyInfo.KeyIndex != 0) &&
224 (pKeyDesc->KeyInfo.KeyAck == 1) &&
225 (pKeyDesc->KeyInfo.KeyMic == 1) &&
226 (pKeyDesc->KeyInfo.Secure == 1) &&
227 (pKeyDesc->KeyInfo.Error == 0) &&
228 (pKeyDesc->KeyInfo.Request == 0))
230 MsgType = EAPOL_GROUP_MSG_1;
231 DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Group Message 1\n");
233 else
234 DBGPRINT(RT_DEBUG_TRACE, "Receive INVALID EAPOL Key Message\n");
236 #ifdef BIG_ENDIAN
237 *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
238 #endif
240 // We will assume link is up (assoc suceess and port not secured).
241 // All state has to be able to process message from previous state
242 switch (pAdapter->PortCfg.WpaState)
244 case SS_START:
245 if (MsgType == EAPOL_PAIR_MSG_1)
247 WpaPairMsg1Action(pAdapter, Elem);
248 pAdapter->PortCfg.WpaState = SS_WAIT_MSG_3;
250 break;
252 case SS_WAIT_MSG_3:
253 if (MsgType == EAPOL_PAIR_MSG_1)
255 WpaPairMsg1Action(pAdapter, Elem);
256 pAdapter->PortCfg.WpaState = SS_WAIT_MSG_3;
258 else if (MsgType == EAPOL_PAIR_MSG_3)
260 WpaPairMsg3Action(pAdapter, Elem);
261 pAdapter->PortCfg.WpaState = SS_WAIT_GROUP;
263 break;
265 case SS_WAIT_GROUP: // When doing group key exchange
266 case SS_FINISH: // This happened when update group key
267 if (MsgType == EAPOL_PAIR_MSG_1)
269 WpaPairMsg1Action(pAdapter, Elem);
270 pAdapter->PortCfg.WpaState = SS_WAIT_MSG_3;
271 // Reset port secured variable
272 pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
274 else if (MsgType == EAPOL_PAIR_MSG_3)
276 WpaPairMsg3Action(pAdapter, Elem);
277 pAdapter->PortCfg.WpaState = SS_WAIT_GROUP;
278 // Reset port secured variable
279 pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
281 else if (MsgType == EAPOL_GROUP_MSG_1)
283 WpaGroupMsg1Action(pAdapter, Elem);
284 pAdapter->PortCfg.WpaState = SS_FINISH;
286 break;
288 default:
289 break;
292 DBGPRINT(RT_DEBUG_TRACE, "<----- WpaEAPOLKeyAction\n");
296 ========================================================================
298 Routine Description:
299 Process Pairwise key 4-way handshaking
301 Arguments:
302 pAdapter Pointer to our adapter
303 Elem Message body
305 Return Value:
306 None
308 Note:
310 ========================================================================
312 VOID WpaPairMsg1Action(
313 IN PRTMP_ADAPTER pAdapter,
314 IN MLME_QUEUE_ELEM *Elem)
316 PHEADER_802_11 pHeader;
317 UCHAR PTK[80];
318 UCHAR *OutBuffer = NULL;
319 HEADER_802_11 Header_802_11;
320 NDIS_STATUS NStatus;
321 UCHAR AckRate = RATE_2;
322 USHORT AckDuration = 0;
323 ULONG FrameLen = 0;
324 UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
325 PEAPOL_PACKET pMsg1;
326 EAPOL_PACKET Packet;
327 UCHAR Mic[16];
329 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg1Action ----->\n");
331 pHeader = (PHEADER_802_11) Elem->Msg;
333 // Save Data Length to pDesc for receiving packet, then put in outgoing frame Data Len fields.
334 pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
336 // Process message 1 from authenticator
337 // Key must be Pairwise key, already verified at callee.
338 // 1. Save Replay counter, it will use to verify message 3 and construct message 2
339 NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
341 // 2. Save ANonce
342 NdisMoveMemory(pAdapter->PortCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
344 // TSNonce <--- SNonce
345 // Generate random SNonce
346 GenRandom(pAdapter, pAdapter->PortCfg.SNonce);
348 // TPTK <--- Calc PTK(ANonce, TSNonce)
349 WpaCountPTK(pAdapter->PortCfg.PskKey.Key,
350 pAdapter->PortCfg.ANonce,
351 pAdapter->PortCfg.Bssid.Octet,
352 pAdapter->PortCfg.SNonce,
353 pAdapter->CurrentAddress,
354 PTK,
355 LEN_PTK);
357 // Save key to PTK entry
358 NdisMoveMemory(pAdapter->PortCfg.PTK, PTK, LEN_PTK);
360 // =====================================
361 // Use Priority Ring & MiniportMMRequest
362 // =====================================
363 pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
364 WpaMacHeaderInit(pAdapter, &Header_802_11, 0, &pAdapter->PortCfg.Bssid);
366 // ACK size is 14 include CRC, and its rate is based on real time information
367 AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
368 AckDuration = RTMPCalcDuration(pAdapter, AckRate, 14);
369 Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
371 // Zero message 2 body
372 NdisZeroMemory(&Packet, sizeof(Packet));
373 Packet.Version = EAPOL_VER;
374 Packet.Type = EAPOLKey;
376 // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
378 Packet.KeyDesc.Type = RSN_KEY_DESC;
379 // 1. Key descriptor version and appropriate RSN IE
380 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
382 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
383 Packet.KeyDesc.KeyDataLen[1] = CipherWpaPskAesLen;
384 NdisMoveMemory(Packet.KeyDesc.KeyData, CipherWpaPskAes, CipherWpaPskAesLen);
386 else // TKIP
388 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
389 Packet.KeyDesc.KeyDataLen[1] = CipherWpaPskTkipLen;
390 NdisMoveMemory(Packet.KeyDesc.KeyData, CipherWpaPskTkip, CipherWpaPskTkipLen);
392 // Update packet length after decide Key data payload
393 Packet.Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
395 // 2. Key Type PeerKey
396 Packet.KeyDesc.KeyInfo.KeyType = 1;
398 // 3. KeyMic field presented
399 Packet.KeyDesc.KeyInfo.KeyMic = 1;
401 // 4. Fill SNonce
402 NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAdapter->PortCfg.SNonce, LEN_KEY_DESC_NONCE);
404 // 5. Key Replay Count
405 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
407 #ifdef BIG_ENDIAN
408 *(USHORT *)(&(Packet.KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(Packet.KeyDesc.KeyInfo)));
409 #endif
411 // Send EAPOL(0, 1, 0, 0, 0, K, 0, TSNonce, 0, MIC(TPTK), 0)
412 // Out buffer for transmitting message 2
413 NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer); //Get an unused nonpaged memory
414 if (NStatus != NDIS_STATUS_SUCCESS)
415 return;
417 // Prepare EAPOL frame for MIC calculation
418 // Be careful, only EAPOL frame is counted for MIC calculation
419 MakeOutgoingFrame(OutBuffer, &FrameLen,
420 Packet.Len[1] + 4, &Packet,
421 END_OF_ARGS);
423 // 5. Prepare and Fill MIC value
424 NdisZeroMemory(Mic, sizeof(Mic));
425 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
427 // AES
428 UCHAR digest[80];
430 HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
431 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
433 else
435 INT i;
436 DBGPRINT(RT_DEBUG_INFO, " PMK = ");
437 for (i = 0; i < 16; i++)
438 DBGPRINT(RT_DEBUG_INFO, "%2x-", pAdapter->PortCfg.PskKey.Key[i]);
440 DBGPRINT(RT_DEBUG_INFO, "\n PTK = ");
441 for (i = 0; i < 64; i++)
442 DBGPRINT(RT_DEBUG_INFO, "%2x-", pAdapter->PortCfg.PTK[i]);
443 DBGPRINT(RT_DEBUG_INFO, "\n FrameLen = %d\n", FrameLen);
445 hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
447 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
449 FrameLen = 0;
450 // Make Transmitting frame
451 MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
452 sizeof(EAPHEAD), EAPHEAD,
453 Packet.Len[1] + 4, &Packet,
454 END_OF_ARGS);
456 // Send using priority queue
457 MiniportMMRequest(pAdapter, OutBuffer, FrameLen);
459 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg1Action <-----\n");
463 ========================================================================
465 Routine Description:
466 Process Pairwise key 4-way handshaking
468 Arguments:
469 pAdapter Pointer to our adapter
470 Elem Message body
472 Return Value:
473 None
475 Note:
477 ========================================================================
479 VOID WpaPairMsg3Action(
480 IN PRTMP_ADAPTER pAdapter,
481 IN MLME_QUEUE_ELEM *Elem)
483 PHEADER_802_11 pHeader;
484 UCHAR *OutBuffer = NULL;
485 HEADER_802_11 Header_802_11;
486 NDIS_STATUS NStatus;
487 UCHAR AckRate = RATE_2;
488 USHORT AckDuration = 0;
489 ULONG FrameLen = 0;
490 UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
491 EAPOL_PACKET Packet;
492 PEAPOL_PACKET pMsg3;
493 PUCHAR pTmp;
494 UCHAR Mic[16], OldMic[16];
495 NDIS_802_11_KEY PeerKey;
498 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg3Action ----->\n");
500 pHeader = (PHEADER_802_11) Elem->Msg;
502 // Process message 3 frame.
503 pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
505 #ifdef BIG_ENDIAN
506 *(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)));
507 #endif
509 // 1. Verify RSN IE & cipher type match
510 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
512 if (pMsg3->KeyDesc.KeyInfo.KeyDescVer != 2)
513 return;
514 pTmp = (PUCHAR) &CipherWpaPskAes;
516 else // TKIP
518 if (pMsg3->KeyDesc.KeyInfo.KeyDescVer != 1)
519 return;
520 pTmp = (PUCHAR) &CipherWpaPskTkip;
523 // Fix compatibility issue, when AP append nonsense data after auth mode with different size.
524 // We should qualify this kind of RSN as acceptable
525 if (!NdisEqualMemory((PUCHAR) &pMsg3->KeyDesc.KeyData[2], pTmp + 2, CipherWpaPskTkipLen - 2))
527 DBGPRINT(RT_DEBUG_ERROR, " RSN IE mismatched msg 3 of 4-way handshake!!!!!!!!!! \n");
528 return;
530 else
531 DBGPRINT(RT_DEBUG_TRACE, " RSN IE matched in msg 3 of 4-way handshake!!!!!!!!!! \n");
533 #ifdef BIG_ENDIAN
534 *(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)));
535 #endif
537 // 2. Check MIC value
538 // Save the MIC and replace with zero
539 NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
540 NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
541 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
543 // AES
544 UCHAR digest[80];
546 HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Len[1] + 4, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
547 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
549 else
551 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Len[1] + 4, Mic);
554 if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
556 DBGPRINT(RT_DEBUG_ERROR, " MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n");
557 return;
559 else
560 DBGPRINT(RT_DEBUG_TRACE, " MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n");
562 // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
563 if (RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
564 return;
566 // Update new replay counter
567 NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
569 // 4. Double check ANonce
570 if (!NdisEqualMemory(pAdapter->PortCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
571 return;
573 // 5. Construct Message 4
574 // =====================================
575 // Use Priority Ring & MiniportMMRequest
576 // =====================================
577 pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
578 WpaMacHeaderInit(pAdapter, &Header_802_11, 0, &pAdapter->PortCfg.Bssid);
580 // ACK size is 14 include CRC, and its rate is based on real time information
581 AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
582 AckDuration = RTMPCalcDuration(pAdapter, AckRate, 14);
583 Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
585 // Zero message 4 body
586 NdisZeroMemory(&Packet, sizeof(Packet));
587 Packet.Version = EAPOL_VER;
588 Packet.Type = EAPOLKey;
589 Packet.Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
592 // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
594 Packet.KeyDesc.Type = RSN_KEY_DESC;
596 #ifdef BIG_ENDIAN
597 *(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)));
598 #endif
600 // Key descriptor version and appropriate RSN IE
601 Packet.KeyDesc.KeyInfo.KeyDescVer = pMsg3->KeyDesc.KeyInfo.KeyDescVer;
603 // Key Type PeerKey
604 Packet.KeyDesc.KeyInfo.KeyType = 1;
606 // KeyMic field presented
607 Packet.KeyDesc.KeyInfo.KeyMic = 1;
609 // Key Replay count
610 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
611 #ifdef BIG_ENDIAN
612 *(USHORT *)&Packet.KeyDesc.KeyInfo = SWAP16(*(USHORT *)&Packet.KeyDesc.KeyInfo);
613 #endif
615 // Out buffer for transmitting message 4
616 NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer); //Get an unused nonpaged memory
617 if (NStatus != NDIS_STATUS_SUCCESS)
618 return;
620 // Prepare EAPOL frame for MIC calculation
621 // Be careful, only EAPOL frame is counted for MIC calculation
622 MakeOutgoingFrame(OutBuffer, &FrameLen,
623 Packet.Len[1] + 4, &Packet,
624 END_OF_ARGS);
626 // Prepare and Fill MIC value
627 NdisZeroMemory(Mic, sizeof(Mic));
628 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
630 // AES
631 UCHAR digest[80];
633 HMAC_SHA1(OutBuffer, FrameLen, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
634 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
636 else
638 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
640 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
642 FrameLen = 0;
644 // Make Transmitting frame
645 MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
646 sizeof(EAPHEAD), EAPHEAD,
647 Packet.Len[1] + 4, &Packet,
648 END_OF_ARGS);
650 // 6. Send Message 4 to authenticator
651 // Send using priority queue
652 MiniportMMRequest(pAdapter, OutBuffer, FrameLen);
654 // 7. Update PTK
655 NdisZeroMemory(&PeerKey, sizeof(PeerKey));
656 PeerKey.Length = sizeof(PeerKey);
657 PeerKey.KeyIndex = 0xe0000000;
658 PeerKey.KeyLength = 16;
659 NdisMoveMemory(PeerKey.BSSID, pAdapter->PortCfg.Bssid.Octet, 6);
660 NdisMoveMemory(&PeerKey.KeyRSC, pMsg3->KeyDesc.KeyRsc, LEN_KEY_DESC_RSC);
661 NdisMoveMemory(PeerKey.KeyMaterial, &pAdapter->PortCfg.PTK[32], 32);
662 // Call Add peer key function
663 RTMPWPAAddKeyProc(pAdapter, &PeerKey);
665 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg3Action <-----\n");
670 ========================================================================
672 Routine Description:
673 Process Group key 2-way handshaking
675 Arguments:
676 pAdapter Pointer to our adapter
677 Elem Message body
679 Return Value:
680 None
682 Note:
684 ========================================================================
686 VOID WpaGroupMsg1Action(
687 IN PRTMP_ADAPTER pAdapter,
688 IN MLME_QUEUE_ELEM *Elem)
690 PHEADER_802_11 pHeader;
691 UCHAR *OutBuffer = NULL;
692 HEADER_802_11 Header_802_11;
693 NDIS_STATUS NStatus;
694 UCHAR AckRate = RATE_2;
695 USHORT AckDuration = 0;
696 ULONG FrameLen = 0;
697 UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
698 EAPOL_PACKET Packet;
699 PEAPOL_PACKET pGroup;
700 UCHAR Mic[16], OldMic[16];
701 UCHAR GTK[32], Key[32];
702 NDIS_802_11_KEY GroupKey;
705 DBGPRINT(RT_DEBUG_TRACE, "WpaGroupMsg1Action ----->\n");
707 pHeader = (PHEADER_802_11) Elem->Msg;
709 // Process Group message 1 frame.
710 pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
712 // 1. Verify Replay counter
713 // Check Replay Counter, it has to be larger than last one. No need to be exact one larger
714 if (RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
715 return;
717 // Update new replay counter
718 NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
720 // 2. Verify MIC is valid
721 // Save the MIC and replace with zero
722 NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
723 NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
724 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
726 // AES
727 UCHAR digest[80];
729 HMAC_SHA1((PUCHAR) pGroup, pGroup->Len[1] + 4, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
730 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
732 else
734 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Len[1] + 4, Mic);
737 if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
739 DBGPRINT(RT_DEBUG_ERROR, " MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n");
740 return;
742 else
743 DBGPRINT(RT_DEBUG_TRACE, " MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n");
745 #ifdef BIG_ENDIAN
746 *(USHORT *)(&(pGroup->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pGroup->KeyDesc.KeyInfo)));
747 #endif
749 // 3. Decrypt GTK from Key Data
750 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
752 if (pGroup->KeyDesc.KeyInfo.KeyDescVer != 2)
753 return;
754 // Decrypt AES GTK
755 AES_GTK_KEY_UNWRAP(&pAdapter->PortCfg.PTK[16], GTK, pGroup->KeyDesc.KeyData);
757 else // TKIP
759 INT i;
761 if (pGroup->KeyDesc.KeyInfo.KeyDescVer != 1)
762 return;
763 // Decrypt TKIP GTK
764 // Construct 32 bytes RC4 Key
765 NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16);
766 NdisMoveMemory(&Key[16], &pAdapter->PortCfg.PTK[16], 16);
767 ARCFOUR_INIT(&pAdapter->PrivateInfo.WEPCONTEXT, Key, 32);
768 //discard first 256 bytes
769 for (i = 0; i < 256; i++)
770 ARCFOUR_BYTE(&pAdapter->PrivateInfo.WEPCONTEXT);
771 // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
772 ARCFOUR_DECRYPT(&pAdapter->PrivateInfo.WEPCONTEXT, GTK, pGroup->KeyDesc.KeyData, 32);
775 // 4. Construct Group Message 2
776 pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
777 WpaMacHeaderInit(pAdapter, &Header_802_11, 1, &pAdapter->PortCfg.Bssid);
779 // ACK size is 14 include CRC, and its rate is based on real time information
780 AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
781 AckDuration = RTMPCalcDuration(pAdapter, AckRate, 14);
782 Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
784 // Zero Group message 1 body
785 NdisZeroMemory(&Packet, sizeof(Packet));
786 Packet.Version = EAPOL_VER;
787 Packet.Type = EAPOLKey;
788 Packet.Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
791 // Group Message 2 as EAPOL-Key(1,0,0,0,G,0,0,MIC,0)
793 Packet.KeyDesc.Type = RSN_KEY_DESC;
795 // Key descriptor version and appropriate RSN IE
796 Packet.KeyDesc.KeyInfo.KeyDescVer = pGroup->KeyDesc.KeyInfo.KeyDescVer;
798 // Key Type Group key
799 Packet.KeyDesc.KeyInfo.KeyType = 0;
801 // KeyMic field presented
802 Packet.KeyDesc.KeyInfo.KeyMic = 1;
804 // Secure bit is 1
805 Packet.KeyDesc.KeyInfo.Secure = 1;
807 // Key Replay count
808 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
810 #ifdef BIG_ENDIAN
811 *(USHORT *)(&(Packet.KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(Packet.KeyDesc.KeyInfo)));
812 #endif
814 // Out buffer for transmitting group message 2
815 NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer); //Get an unused nonpaged memory
816 if (NStatus != NDIS_STATUS_SUCCESS)
817 return;
819 // Prepare EAPOL frame for MIC calculation
820 // Be careful, only EAPOL frame is counted for MIC calculation
821 MakeOutgoingFrame(OutBuffer, &FrameLen,
822 Packet.Len[1] + 4, &Packet,
823 END_OF_ARGS);
825 // Prepare and Fill MIC value
826 NdisZeroMemory(Mic, sizeof(Mic));
827 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
829 // AES
830 UCHAR digest[80];
832 HMAC_SHA1(OutBuffer, FrameLen, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
833 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
835 else
837 INT i;
838 DBGPRINT(RT_DEBUG_INFO, "PTK = ");
839 for (i = 0; i < 64; i++)
840 DBGPRINT(RT_DEBUG_INFO, "%2x-", pAdapter->PortCfg.PTK[i]);
841 DBGPRINT(RT_DEBUG_INFO, "\n FrameLen = %d\n", FrameLen);
843 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
845 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
847 FrameLen = 0;
848 // Make Transmitting frame
849 MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
850 sizeof(EAPHEAD), EAPHEAD,
851 Packet.Len[1] + 4, &Packet,
852 END_OF_ARGS);
854 // 5. Copy frame to Tx ring and prepare for encryption
855 WpaHardEncrypt(pAdapter, OutBuffer, FrameLen);
857 // 6 Free allocated memory
858 MlmeFreeMemory(pAdapter, OutBuffer);
860 // 6. Update GTK
861 NdisZeroMemory(&GroupKey, sizeof(GroupKey));
862 GroupKey.Length = sizeof(GroupKey);
863 GroupKey.KeyIndex = 0x20000000 | pGroup->KeyDesc.KeyInfo.KeyIndex;
864 GroupKey.KeyLength = 16;
865 NdisMoveMemory(GroupKey.BSSID, pAdapter->PortCfg.Bssid.Octet, 6);
866 NdisMoveMemory(GroupKey.KeyMaterial, GTK, 32);
867 // Call Add peer key function
868 RTMPWPAAddKeyProc(pAdapter, &GroupKey);
870 DBGPRINT(RT_DEBUG_TRACE, "WpaGroupMsg1Action <-----\n");
873 ========================================================================
875 Routine Description:
876 Init WPA MAC header
878 Arguments:
879 pAdapter Pointer to our adapter
881 Return Value:
882 None
884 Note:
886 ========================================================================
888 VOID WpaMacHeaderInit(
889 IN PRTMP_ADAPTER pAd,
890 IN OUT PHEADER_802_11 Hdr,
891 IN UCHAR wep,
892 IN PMACADDR pAddr1)
894 NdisZeroMemory(Hdr, sizeof(HEADER_802_11));
895 Hdr->Controlhead.Frame.Type = BTYPE_DATA;
896 Hdr->Controlhead.Frame.ToDs = 1;
897 if (wep == 1)
898 Hdr->Controlhead.Frame.Wep = 1;
900 // Addr1: DA, Addr2: BSSID, Addr3: SA
901 COPY_MAC_ADDR(&Hdr->Controlhead.Addr1, pAddr1);
902 COPY_MAC_ADDR(&Hdr->Controlhead.Addr2, &pAd->CurrentAddress);
903 COPY_MAC_ADDR(&Hdr->Addr3, &pAd->PortCfg.Bssid);
904 Hdr->Sequence = pAd->Sequence;
908 ========================================================================
910 Routine Description:
911 Copy frame from waiting queue into relative ring buffer and set
912 appropriate ASIC register to kick hardware encryption before really
913 sent out to air.
915 Arguments:
916 pAdapter Pointer to our adapter
917 PNDIS_PACKET Pointer to outgoing Ndis frame
918 NumberOfFrag Number of fragment required
920 Return Value:
921 None
923 Note:
925 ========================================================================
927 VOID WpaHardEncrypt(
928 IN PRTMP_ADAPTER pAdapter,
929 IN PUCHAR pPacket,
930 IN ULONG Len)
932 UCHAR FrameGap;
933 PUCHAR pDest;
934 PUCHAR pSrc;
935 UCHAR CipherAlg = CIPHER_NONE;
936 PTXD_STRUC pTxD;
937 #ifdef BIG_ENDIAN
938 TXD_STRUC TxD;
939 PTXD_STRUC pDestTxD;
940 PUCHAR pOriginDest;
941 #endif
942 ULONG Iv16;
943 ULONG Iv32;
944 PWPA_KEY pWpaKey = NULL;
945 UCHAR RetryMode = SHORT_RETRY;
946 static UCHAR Priority[4] = {"\x00\x00\x00\x00"};
947 INT idx;
948 PHEADER_802_11 pHeader;
949 ULONG IrqFlags;
951 // Make sure Tx ring resource won't be used by other threads
952 NdisAcquireSpinLock(&pAdapter->TxRingLock, IrqFlags);
954 FrameGap = IFS_BACKOFF; // Default frame gap mode
956 // outgoing frame always wakeup PHY to prevent frame lost and
957 // turn off PSM bit to improve performance
958 if (pAdapter->PortCfg.Psm == PWR_SAVE)
960 MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
962 AsicForceWakeup(pAdapter);
964 pAdapter->TxRing[pAdapter->CurEncryptIndex].FrameType = BTYPE_DATA;
966 pSrc = pPacket; // Point to start of MSDU
968 #if 0
969 pWpaKey = (PWPA_KEY) &pAdapter->PortCfg.PairwiseKey[0];
970 pWpaKey->Type = PAIRWISE_KEY;
971 #else
972 pHeader = (PHEADER_802_11) pSrc;
974 for (idx = 0; idx < PAIRWISE_KEY_NO; idx++)
976 if ((NdisEqualMemory(&pHeader->Controlhead.Addr1, pAdapter->PortCfg.PairwiseKey[idx].BssId, 6)) &&
977 (pAdapter->PortCfg.PairwiseKey[idx].KeyLen != 0))
979 pWpaKey = (PWPA_KEY) &pAdapter->PortCfg.PairwiseKey[idx];
980 pWpaKey->Type = PAIRWISE_KEY;
981 DBGPRINT(RT_DEBUG_TRACE, "WpaHardEncrypt:(U) Tx Use Pairwise Key(%d)\n", idx);
982 break;
985 #endif
987 if (pWpaKey == NULL)
989 // No pairwise key, this should not happen
990 DBGPRINT(RT_DEBUG_ERROR, "WpaHardEncrypt: No pairwise key!!!!!!!!!!!\n");
991 NdisReleaseSpinLock(&pAdapter->TxRingLock, IrqFlags);
992 return;
995 // Get the Tx Ring descriptor & Dma Buffer address
996 pDest = (PUCHAR) pAdapter->TxRing[pAdapter->CurEncryptIndex].va_data_addr;
997 #ifndef BIG_ENDIAN
998 pTxD = (PTXD_STRUC) pAdapter->TxRing[pAdapter->CurEncryptIndex].va_addr;
999 #else
1000 pOriginDest = pDest;
1001 pDestTxD = (PTXD_STRUC) pAdapter->TxRing[pAdapter->CurEncryptIndex].va_addr;
1002 TxD = *pDestTxD;
1003 pTxD = &TxD;
1004 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1005 #endif
1007 if ((pTxD->Owner == DESC_OWN_NIC) || (pTxD->CipherOwn == DESC_OWN_NIC))
1009 // Descriptor owned by NIC. No descriptor avaliable
1010 // This should not happen since caller guaranteed.
1011 // Make sure to release Tx ring resource
1012 DBGPRINT(RT_DEBUG_ERROR, "WpaHardEncrypt: Descriptor owned by NIC. No descriptor avaliable!!!!!!!!!!!\n");
1013 pAdapter->RalinkCounters.TxRingErrCount++;
1014 NdisReleaseSpinLock(&pAdapter->TxRingLock, IrqFlags);
1015 return;
1017 if (pTxD->Valid == TRUE)
1019 // Ndis packet of last round did not cleared.
1020 // This should not happen since caller guaranteed.
1021 // Make sure to release Tx ring resource
1022 pTxD->Valid = FALSE;
1024 #ifdef BIG_ENDIAN
1025 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1026 *pDestTxD = TxD;
1027 #endif
1028 DBGPRINT(RT_DEBUG_ERROR, "WpaHardEncrypt: Ndis packet of last round did not cleared!!!!!!!!!!!\n");
1029 pAdapter->RalinkCounters.TxRingErrCount++;
1030 NdisReleaseSpinLock(&pAdapter->TxRingLock, IrqFlags);
1031 return;
1034 // Copy whole frame to Tx ring buffer
1035 NdisMoveMemory(pDest, pPacket, Len);
1036 pDest += Len;
1038 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled)
1040 INT i;
1042 i = 0;
1043 // Prepare 8 bytes TKIP encapsulation for MPDU
1045 TKIP_IV tkipIv;
1047 tkipIv.IV16.field.rc0 = *(pWpaKey->TxTsc + 1);
1048 tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f;
1049 tkipIv.IV16.field.rc2 = *pWpaKey->TxTsc;
1051 tkipIv.IV16.field.Rsvd = 0;
1052 tkipIv.IV16.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV
1053 tkipIv.IV16.field.KeyID = 0;
1055 //tkipIv.IV32 = *(PULONG)(pWpaKey->TxTsc + 2);
1056 NdisMoveMemory(&tkipIv.IV32, &pWpaKey->TxTsc[2], 4);
1058 #ifdef BIG_ENDIAN
1059 pTxD->Iv = SWAP32(tkipIv.IV16.word);
1060 #else
1061 pTxD->Iv = tkipIv.IV16.word;
1062 #endif
1064 *((PUCHAR) &pTxD->Eiv) = *((PUCHAR) &tkipIv.IV32 + 3);
1065 *((PUCHAR) &pTxD->Eiv + 1) = *((PUCHAR) &tkipIv.IV32 + 2);
1066 *((PUCHAR) &pTxD->Eiv + 2) = *((PUCHAR) &tkipIv.IV32 + 1);
1067 *((PUCHAR) &pTxD->Eiv + 3) = *((PUCHAR) &tkipIv.IV32);
1070 // Increase TxTsc value for next transmission
1071 while (++pWpaKey->TxTsc[i] == 0x0)
1073 i++;
1074 if (i == 6)
1075 break;
1078 // Set IV offset
1079 pTxD->IvOffset = LENGTH_802_11;
1081 // Copy TKey
1082 NdisMoveMemory(pTxD->Key, pWpaKey->Key, 16);
1084 // Set Cipher suite
1085 CipherAlg = CIPHER_TKIP;
1087 // Calculate MIC value
1088 // Init MIC value calculation and reset the message
1089 pAdapter->PrivateInfo.Tx.L = RTMPTkipGetUInt32(pWpaKey->TxMic);
1090 pAdapter->PrivateInfo.Tx.R = RTMPTkipGetUInt32(pWpaKey->TxMic + 4);
1091 pAdapter->PrivateInfo.Tx.nBytesInM = 0;
1092 pAdapter->PrivateInfo.Tx.M = 0;
1094 // DA & SA field
1095 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc + 4, 12);
1097 // Priority + 3 bytes of 0
1098 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, Priority, 4);
1100 pSrc += LENGTH_802_11;
1101 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc, Len - LENGTH_802_11);
1102 RTMPTkipGetMIC(&pAdapter->PrivateInfo.Tx);
1103 // Append MIC
1104 NdisMoveMemory(pDest, pAdapter->PrivateInfo.Tx.MIC, 8);
1105 Len += 8;
1106 // IV + EIV + ICV which ASIC added after encryption done
1107 Len += 12;
1109 else if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
1111 INT i;
1112 PUCHAR pTmp;
1114 i = 0;
1115 pTmp = (PUCHAR) &Iv16;
1116 *pTmp = pWpaKey->TxTsc[0];
1117 *(pTmp + 1) = pWpaKey->TxTsc[1];
1118 *(pTmp + 2) = 0;
1119 *(pTmp + 3) = 0x20;
1121 Iv32 = *(PULONG)(&pWpaKey->TxTsc[2]);
1123 // Increase TxTsc value for next transmission
1124 while (++pWpaKey->TxTsc[i] == 0x0)
1126 i++;
1127 if (i == 6)
1128 break;
1131 // Copy IV
1132 NdisMoveMemory(&pTxD->Iv, &Iv16, 4);
1134 // Copy EIV
1135 NdisMoveMemory(&pTxD->Eiv, &Iv32, 4);
1137 // Set IV offset
1138 pTxD->IvOffset = LENGTH_802_11;
1140 // Copy TKey
1141 NdisMoveMemory(pTxD->Key, pWpaKey->Key, 16);
1143 // Set Cipher suite
1144 CipherAlg = CIPHER_AES;
1146 // IV + EIV + HW MIC
1147 Len += 16;
1150 #ifdef BIG_ENDIAN
1151 RTMPFrameEndianChange(pAdapter, pOriginDest, DIR_WRITE, FALSE);
1152 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1153 *pDestTxD = TxD;
1154 pTxD = pDestTxD;
1155 #endif
1157 RTMPWriteTxDescriptor(pTxD, TRUE, CipherAlg, TRUE, FALSE, FALSE, RetryMode, FrameGap,
1158 pAdapter->PortCfg.TxRate, 4, Len, pAdapter->PortCfg.TxPreambleInUsed, 0);
1160 // Increase & maintain Tx Ring Index
1161 pAdapter->CurEncryptIndex++;
1162 if (pAdapter->CurEncryptIndex >= TX_RING_SIZE)
1164 pAdapter->CurEncryptIndex = 0;
1166 pAdapter->RalinkCounters.EncryptCount++;
1168 // Kick Encrypt Control Register at the end of all ring buffer preparation
1169 RTMP_IO_WRITE32(pAdapter, SECCSR1, 0x1);
1171 // Make sure to release Tx ring resource
1172 NdisReleaseSpinLock(&pAdapter->TxRingLock, IrqFlags);
1176 ========================================================================
1178 Routine Description:
1179 SHA1 function
1181 Arguments:
1183 Return Value:
1185 Note:
1187 ========================================================================
1189 VOID HMAC_SHA1(
1190 IN UCHAR *text,
1191 IN UINT text_len,
1192 IN UCHAR *key,
1193 IN UINT key_len,
1194 IN UCHAR *digest)
1196 SHA_CTX context;
1197 UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
1198 UCHAR k_opad[65]; /* outer padding - key XORd with opad */
1199 INT i;
1201 // if key is longer than 64 bytes reset it to key=SHA1(key)
1202 if (key_len > 64)
1204 SHA_CTX tctx;
1205 SHAInit(&tctx);
1206 SHAUpdate(&tctx, key, key_len);
1207 SHAFinal(&tctx, key);
1208 key_len = 20;
1210 NdisZeroMemory(k_ipad, sizeof(k_ipad));
1211 NdisZeroMemory(k_opad, sizeof(k_opad));
1212 NdisMoveMemory(k_ipad, key, key_len);
1213 NdisMoveMemory(k_opad, key, key_len);
1215 // XOR key with ipad and opad values
1216 for (i = 0; i < 64; i++)
1218 k_ipad[i] ^= 0x36;
1219 k_opad[i] ^= 0x5c;
1222 // perform inner SHA1
1223 SHAInit(&context); /* init context for 1st pass */
1224 SHAUpdate(&context, k_ipad, 64); /* start with inner pad */
1225 SHAUpdate(&context, text, text_len); /* then text of datagram */
1226 SHAFinal(&context, digest); /* finish up 1st pass */
1228 //perform outer SHA1
1229 SHAInit(&context); /* init context for 2nd pass */
1230 SHAUpdate(&context, k_opad, 64); /* start with outer pad */
1231 SHAUpdate(&context, digest, 20); /* then results of 1st hash */
1232 SHAFinal(&context, digest); /* finish up 2nd pass */
1236 ========================================================================
1238 Routine Description:
1239 PRF function
1241 Arguments:
1243 Return Value:
1245 Note:
1246 802.1i Annex F.9
1248 ========================================================================
1250 VOID PRF(
1251 IN UCHAR *key,
1252 IN INT key_len,
1253 IN UCHAR *prefix,
1254 IN INT prefix_len,
1255 IN UCHAR *data,
1256 IN INT data_len,
1257 OUT UCHAR *output,
1258 IN INT len)
1260 INT i;
1261 UCHAR input[1024];
1262 INT currentindex = 0;
1263 INT total_len;
1265 NdisMoveMemory(input, prefix, prefix_len);
1266 input[prefix_len] = 0;
1267 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1268 total_len = prefix_len + 1 + data_len;
1269 input[total_len] = 0;
1270 total_len++;
1271 for (i = 0; i < (len + 19) / 20; i++)
1273 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
1274 currentindex += 20;
1275 input[total_len - 1]++;
1280 ========================================================================
1282 Routine Description:
1283 Count TPTK from PMK
1285 Arguments:
1287 Return Value:
1288 Output Store the TPTK
1290 Note:
1292 ========================================================================
1294 VOID WpaCountPTK(
1295 IN UCHAR *PMK,
1296 IN UCHAR *ANonce,
1297 IN UCHAR *AA,
1298 IN UCHAR *SNonce,
1299 IN UCHAR *SA,
1300 OUT UCHAR *output,
1301 IN UINT len)
1303 UCHAR concatenation[76];
1304 UINT CurrPos = 0;
1305 UCHAR temp[32];
1306 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1307 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
1309 NdisZeroMemory(temp, sizeof(temp));
1311 // Get smaller address
1312 if (RTMPCompareMemory(SA, AA, 6) == 1)
1313 NdisMoveMemory(concatenation, AA, 6);
1314 else
1315 NdisMoveMemory(concatenation, SA, 6);
1316 CurrPos += 6;
1318 // Get larger address
1319 if (RTMPCompareMemory(SA, AA, 6) == 1)
1320 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1321 else
1322 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1323 CurrPos += 6;
1325 // Get smaller address
1326 if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1327 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1328 else
1329 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1330 CurrPos += 32;
1332 // Get larger address
1333 if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1334 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1335 else
1336 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1337 CurrPos += 32;
1339 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76 , output, len);
1343 ========================================================================
1345 Routine Description:
1346 Misc function to Generate random number
1348 Arguments:
1350 Return Value:
1352 Note:
1353 802.1i Annex F.9
1355 ========================================================================
1357 VOID GenRandom(
1358 IN PRTMP_ADAPTER pAd,
1359 OUT UCHAR *random)
1361 INT i, curr;
1362 UCHAR local[80], KeyCounter[32];
1363 UCHAR result[80];
1364 ULONG CurrentTime;
1365 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
1367 NdisZeroMemory(result, 80);
1368 NdisZeroMemory(local, 80);
1369 NdisZeroMemory(KeyCounter, 32);
1370 NdisMoveMemory(local, pAd->CurrentAddress, ETH_LENGTH_OF_ADDRESS);
1372 for (i = 0; i < 32; i++)
1374 curr = ETH_LENGTH_OF_ADDRESS;
1375 CurrentTime = jiffies;
1376 NdisMoveMemory(local, pAd->CurrentAddress, ETH_LENGTH_OF_ADDRESS);
1377 curr += ETH_LENGTH_OF_ADDRESS;
1378 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1379 curr += sizeof(CurrentTime);
1380 NdisMoveMemory(&local[curr], result, 32);
1381 curr += 32;
1382 NdisMoveMemory(&local[curr], &i, 2);
1383 curr += 2;
1384 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
1386 NdisMoveMemory(random, result, 32);
1390 ========================================================================
1392 Routine Description:
1393 Misc function to decrypt AES body
1395 Arguments:
1397 Return Value:
1399 Note:
1400 This function references to RFC 3394 for aes key unwrap algorithm.
1402 ========================================================================
1404 VOID AES_GTK_KEY_UNWRAP(
1405 IN UCHAR *key,
1406 OUT UCHAR *plaintext,
1407 IN UCHAR *ciphertext)
1409 UCHAR A[8], BIN[16], BOUT[16];
1410 UCHAR R1[8],R2[8];
1411 UCHAR xor;
1412 INT num_blocks = 2;
1413 INT j;
1414 aes_context aesctx;
1416 // Initialize
1417 // A = C[0]
1418 NdisMoveMemory(A, ciphertext, 8);
1419 // R1 = C1
1420 NdisMoveMemory(R1, &ciphertext[8], 8);
1421 // R2 = C2
1422 NdisMoveMemory(R2, &ciphertext[16], 8);
1424 aes_set_key(&aesctx, key, 128);
1426 for (j = 5; j >= 0; j--)
1428 xor = num_blocks * j + 2;
1429 NdisMoveMemory(BIN, A, 8);
1430 BIN[7] = A[7] ^ xor;
1431 NdisMoveMemory(&BIN[8], R2, 8);
1432 aes_decrypt(&aesctx, BIN, BOUT);
1433 NdisMoveMemory(A, &BOUT[0], 8);
1434 NdisMoveMemory(R2, &BOUT[8], 8);
1436 xor = num_blocks * j + 1;
1437 NdisMoveMemory(BIN, A, 8);
1438 BIN[7] = A[7] ^ xor;
1439 NdisMoveMemory(&BIN[8], R1, 8);
1440 aes_decrypt(&aesctx, BIN, BOUT);
1441 NdisMoveMemory(A, &BOUT[0], 8);
1442 NdisMoveMemory(R1, &BOUT[8], 8);
1445 // OUTPUT
1446 NdisMoveMemory(&plaintext[0], R1, 8);
1447 NdisMoveMemory(&plaintext[8], R2, 8);