MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / net / wireless / rtlink.org / wpa.c
blob91a6fc89c04e823b46de2e06853d3388d08c8f32
1 /*
2 ***************************************************************************
3 * Ralink Tech Inc.
4 * 4F, No. 2 Technology 5th Rd.
5 * Science-based Industrial Park
6 * Hsin-chu, Taiwan, R.O.C.
8 * (c) Copyright 2002, Ralink Technology, Inc.
10 * All rights reserved. Ralink's source code is an unpublished work and the
11 * use of a copyright notice does not imply otherwise. This source code
12 * contains confidential trade secret material of Ralink Tech. Any attemp
13 * or participation in deciphering, decoding, reverse engineering or in any
14 * way altering the source code is stricitly prohibited, unless the prior
15 * written consent of Ralink Technology, Inc. is obtained.
16 ***************************************************************************
18 Module Name:
19 wpa.c
21 Abstract:
23 Revision History:
24 Who When What
25 -------- ---------- ----------------------------------------------
26 Jan Lee 03-07-22 Initial
27 Paul Lin 03-11-28 Modify for supplicant
29 #include "rt_config.h"
31 UCHAR CipherWpaPskTkip[] = {
32 0xDD, 0x16, // RSN IE
33 0x00, 0x50, 0xf2, 0x01, // oui
34 0x01, 0x00, // Version
35 0x00, 0x50, 0xf2, 0x02, // Multicast
36 0x01, 0x00, // Number of unicast
37 0x00, 0x50, 0xf2, 0x02, // unicast
38 0x01, 0x00, // number of authentication method
39 0x00, 0x50, 0xf2, 0x02 // authentication
41 UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR));
43 UCHAR CipherWpaPskAes[] = {
44 0xDD, 0x16, // RSN IE
45 0x00, 0x50, 0xf2, 0x01, // oui
46 0x01, 0x00, // Version
47 0x00, 0x50, 0xf2, 0x04, // Multicast
48 0x01, 0x00, // Number of unicast
49 0x00, 0x50, 0xf2, 0x04, // unicast
50 0x01, 0x00, // number of authentication method
51 0x00, 0x50, 0xf2, 0x02 // authentication
53 UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR));
56 ========================================================================
58 Routine Description:
59 Classify WPA EAP message type
61 Arguments:
62 EAPType Value of EAP message type
63 MsgType Internal Message definition for MLME state machine
65 Return Value:
66 TRUE Found appropriate message type
67 FALSE No appropriate message type
69 Note:
70 All these constants are defined in wpa.h
71 For supplicant, there is only EAPOL Key message avaliable
73 ========================================================================
75 BOOLEAN WpaMsgTypeSubst(
76 IN UCHAR EAPType,
77 OUT ULONG *MsgType)
79 switch (EAPType)
81 case EAPPacket:
82 *MsgType = EAP_MSG_TYPE_EAPPacket;
83 break;
84 case EAPOLStart:
85 *MsgType = EAP_MSG_TYPE_EAPOLStart;
86 break;
87 case EAPOLLogoff:
88 *MsgType = EAP_MSG_TYPE_EAPOLLogoff;
89 break;
90 case EAPOLKey:
91 *MsgType = EAP_MSG_TYPE_EAPOLKey;
92 break;
93 case EAPOLASFAlert:
94 *MsgType = EAP_MSG_TYPE_EAPOLASFAlert;
95 break;
96 default:
97 DBGPRINT(RT_DEBUG_INFO, "WpaMsgTypeSubst : return FALSE; \n");
98 return FALSE;
100 return TRUE;
104 ==========================================================================
105 Description:
106 association state machine init, including state transition and timer init
107 Parameters:
108 S - pointer to the association state machine
109 ==========================================================================
111 VOID WpaPskStateMachineInit(
112 IN PRTMP_ADAPTER pAd,
113 IN STATE_MACHINE *S,
114 OUT STATE_MACHINE_FUNC Trans[])
116 StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE);
117 StateMachineSetAction(S, WPA_PSK_IDLE, EAP_MSG_TYPE_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
121 ==========================================================================
122 Description:
123 This is state machine function.
124 When receiving EAPOL packets which is for 802.1x key management.
125 Use both in WPA, and WPAPSK case.
126 In this function, further dispatch to different functions according to the received packet. 3 categories are :
127 1. normal 4-way pairwisekey and 2-way groupkey handshake
128 2. MIC error (Countermeasures attack) report packet from STA.
129 3. Request for pairwise/group key update from STA
130 Return:
131 ==========================================================================
133 VOID WpaEAPOLKeyAction(
134 IN PRTMP_ADAPTER pAdapter,
135 IN MLME_QUEUE_ELEM *Elem)
137 INT MsgType;
138 UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
139 PKEY_DESCRIPTER pKeyDesc;
141 DBGPRINT(RT_DEBUG_TRACE, "-----> WpaEAPOLKeyAction\n");
142 // Get 802.11 header first
143 pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)];
145 #ifdef BIG_ENDIAN
146 *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
147 #endif
148 // Sanity check, this should only happen in WPA-PSK mode
149 if (pAdapter->PortCfg.AuthMode != Ndis802_11AuthModeWPAPSK)
150 return;
152 // 0. Debug print all bit information
153 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Description Version %d\n", pKeyDesc->KeyInfo.KeyDescVer);
154 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Type %d\n", pKeyDesc->KeyInfo.KeyType);
155 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Index %d\n", pKeyDesc->KeyInfo.KeyIndex);
156 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Install %d\n", pKeyDesc->KeyInfo.Install);
157 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key Ack %d\n", pKeyDesc->KeyInfo.KeyAck);
158 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Key MIC %d\n", pKeyDesc->KeyInfo.KeyMic);
159 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Secure %d\n", pKeyDesc->KeyInfo.Secure);
160 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Error %d\n", pKeyDesc->KeyInfo.Error);
161 DBGPRINT(RT_DEBUG_INFO, "KeyInfo Request %d\n", pKeyDesc->KeyInfo.Request);
162 DBGPRINT(RT_DEBUG_INFO, "KeyInfo DL %d\n", pKeyDesc->KeyInfo.DL);
164 // 1. Check EAPOL frame version and type
165 if ((Elem->Msg[LENGTH_802_11+LENGTH_802_1_H] != EAPOL_VER) || (pKeyDesc->Type != RSN_KEY_DESC))
167 DBGPRINT(RT_DEBUG_ERROR, " Key descripter does not match with WPA rule \n");
168 return;
171 // 2.Check Version for AES & TKIP
172 if ((pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled) && (pKeyDesc->KeyInfo.KeyDescVer != DESC_TYPE_AES))
174 DBGPRINT(RT_DEBUG_ERROR, " Key descripter version not match AES \n");
175 return;
177 else if ((pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) && (pKeyDesc->KeyInfo.KeyDescVer != DESC_TYPE_TKIP))
179 DBGPRINT(RT_DEBUG_ERROR, " Key descripter version not match TKIP \n");
180 return;
183 // First validate replay counter, only accept message with larger replay counter
184 // Let equal pass, some AP start with all zero replay counter
185 NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
186 if ((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
187 (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
188 return;
190 // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant
191 MsgType = EAPOL_MSG_INVALID;
192 if ((pKeyDesc->KeyInfo.KeyType == 1) &&
193 (pKeyDesc->KeyInfo.KeyIndex == 0) &&
194 (pKeyDesc->KeyInfo.KeyAck == 1) &&
195 (pKeyDesc->KeyInfo.KeyMic == 0) &&
196 (pKeyDesc->KeyInfo.Secure == 0) &&
197 (pKeyDesc->KeyInfo.Error == 0) &&
198 (pKeyDesc->KeyInfo.Request == 0))
200 MsgType = EAPOL_PAIR_MSG_1;
201 DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Pairwise Message 1\n");
203 else if ((pKeyDesc->KeyInfo.KeyType == 1) &&
204 (pKeyDesc->KeyInfo.KeyIndex == 0) &&
205 (pKeyDesc->KeyInfo.KeyAck == 1) &&
206 (pKeyDesc->KeyInfo.KeyMic == 1) &&
207 (pKeyDesc->KeyInfo.Secure == 0) &&
208 (pKeyDesc->KeyInfo.Error == 0) &&
209 (pKeyDesc->KeyInfo.Request == 0))
211 MsgType = EAPOL_PAIR_MSG_3;
212 DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Pairwise Message 3\n");
214 else if ((pKeyDesc->KeyInfo.KeyType == 0) &&
215 (pKeyDesc->KeyInfo.KeyIndex != 0) &&
216 (pKeyDesc->KeyInfo.KeyAck == 1) &&
217 (pKeyDesc->KeyInfo.KeyMic == 1) &&
218 (pKeyDesc->KeyInfo.Secure == 1) &&
219 (pKeyDesc->KeyInfo.Error == 0) &&
220 (pKeyDesc->KeyInfo.Request == 0))
222 MsgType = EAPOL_GROUP_MSG_1;
223 DBGPRINT(RT_DEBUG_TRACE, "Receive EAPOL Key Group Message 1\n");
226 #ifdef BIG_ENDIAN
227 *(USHORT *)((UCHAR *)pKeyDesc+1) = SWAP16(*(USHORT *)((UCHAR *)pKeyDesc+1));
228 #endif
230 // We will assume link is up (assoc suceess and port not secured).
231 // All state has to be able to process message from previous state
232 switch (pAdapter->PortCfg.WpaState)
234 case SS_START:
235 if (MsgType == EAPOL_PAIR_MSG_1)
237 WpaPairMsg1Action(pAdapter, Elem);
238 pAdapter->PortCfg.WpaState = SS_WAIT_MSG_3;
240 break;
242 case SS_WAIT_MSG_3:
243 if (MsgType == EAPOL_PAIR_MSG_1)
245 WpaPairMsg1Action(pAdapter, Elem);
246 pAdapter->PortCfg.WpaState = SS_WAIT_MSG_3;
248 else if (MsgType == EAPOL_PAIR_MSG_3)
250 WpaPairMsg3Action(pAdapter, Elem);
251 pAdapter->PortCfg.WpaState = SS_WAIT_GROUP;
253 break;
255 case SS_WAIT_GROUP: // When doing group key exchange
256 case SS_FINISH: // This happened when update group key
257 if (MsgType == EAPOL_PAIR_MSG_1)
259 WpaPairMsg1Action(pAdapter, Elem);
260 pAdapter->PortCfg.WpaState = SS_WAIT_MSG_3;
261 // Reset port secured variable
262 pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
264 else if (MsgType == EAPOL_PAIR_MSG_3)
266 WpaPairMsg3Action(pAdapter, Elem);
267 pAdapter->PortCfg.WpaState = SS_WAIT_GROUP;
268 // Reset port secured variable
269 pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
271 else if (MsgType == EAPOL_GROUP_MSG_1)
273 WpaGroupMsg1Action(pAdapter, Elem);
274 pAdapter->PortCfg.WpaState = SS_FINISH;
276 break;
278 default:
279 break;
282 DBGPRINT(RT_DEBUG_TRACE, "<----- WpaEAPOLKeyAction\n");
286 ========================================================================
288 Routine Description:
289 Process Pairwise key 4-way handshaking
291 Arguments:
292 pAdapter Pointer to our adapter
293 Elem Message body
295 Return Value:
296 None
298 Note:
300 ========================================================================
302 VOID WpaPairMsg1Action(
303 IN PRTMP_ADAPTER pAdapter,
304 IN MLME_QUEUE_ELEM *Elem)
306 PHEADER_802_11 pHeader;
307 UCHAR PTK[80];
308 UCHAR *OutBuffer = NULL;
309 HEADER_802_11 Header_802_11;
310 NDIS_STATUS NStatus;
311 UCHAR AckRate = RATE_2;
312 USHORT AckDuration = 0;
313 ULONG FrameLen = 0;
314 UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
315 PEAPOL_PACKET pMsg1;
316 EAPOL_PACKET Packet;
317 UCHAR Mic[16];
319 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg1Action ----->\n");
321 pHeader = (PHEADER_802_11) Elem->Msg;
323 // Save Data Length to pDesc for receiving packet, then put in outgoing frame Data Len fields.
324 pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
326 // Process message 1 from authenticator
327 // Key must be Pairwise key, already verified at callee.
328 // 1. Save Replay counter, it will use to verify message 3 and construct message 2
329 NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
331 // 2. Save ANonce
332 NdisMoveMemory(pAdapter->PortCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
334 // TSNonce <--- SNonce
335 // Generate random SNonce
336 GenRandom(pAdapter, pAdapter->PortCfg.SNonce);
338 // TPTK <--- Calc PTK(ANonce, TSNonce)
339 WpaCountPTK(pAdapter->PortCfg.PskKey.Key,
340 pAdapter->PortCfg.ANonce,
341 pAdapter->PortCfg.Bssid.Octet,
342 pAdapter->PortCfg.SNonce,
343 pAdapter->CurrentAddress,
344 PTK,
345 LEN_PTK);
347 // Save key to PTK entry
348 NdisMoveMemory(pAdapter->PortCfg.PTK, PTK, LEN_PTK);
350 // =====================================
351 // Use Priority Ring & MiniportMMRequest
352 // =====================================
353 pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
354 WpaMacHeaderInit(pAdapter, &Header_802_11, 0, &pAdapter->PortCfg.Bssid);
356 // ACK size is 14 include CRC, and its rate is based on real time information
357 AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
358 AckDuration = RTMPCalcDuration(pAdapter, AckRate, 14);
359 Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
361 // Zero message 2 body
362 NdisZeroMemory(&Packet, sizeof(Packet));
363 Packet.Version = EAPOL_VER;
364 Packet.Type = EAPOLKey;
366 // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
368 Packet.KeyDesc.Type = RSN_KEY_DESC;
369 // 1. Key descriptor version and appropriate RSN IE
370 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
372 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
373 Packet.KeyDesc.KeyDataLen[1] = CipherWpaPskAesLen;
374 NdisMoveMemory(Packet.KeyDesc.KeyData, CipherWpaPskAes, CipherWpaPskAesLen);
376 else // TKIP
378 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
379 Packet.KeyDesc.KeyDataLen[1] = CipherWpaPskTkipLen;
380 NdisMoveMemory(Packet.KeyDesc.KeyData, CipherWpaPskTkip, CipherWpaPskTkipLen);
382 // Update packet length after decide Key data payload
383 Packet.Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
385 // 2. Key Type PeerKey
386 Packet.KeyDesc.KeyInfo.KeyType = 1;
388 // 3. KeyMic field presented
389 Packet.KeyDesc.KeyInfo.KeyMic = 1;
391 // 4. Fill SNonce
392 NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAdapter->PortCfg.SNonce, LEN_KEY_DESC_NONCE);
394 // 5. Key Replay Count
395 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
397 #ifdef BIG_ENDIAN
398 *(USHORT *)(&(Packet.KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(Packet.KeyDesc.KeyInfo)));
399 #endif
401 // Send EAPOL(0, 1, 0, 0, 0, K, 0, TSNonce, 0, MIC(TPTK), 0)
402 // Out buffer for transmitting message 2
403 NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer); //Get an unused nonpaged memory
404 if (NStatus != NDIS_STATUS_SUCCESS)
405 return;
407 // Prepare EAPOL frame for MIC calculation
408 // Be careful, only EAPOL frame is counted for MIC calculation
409 MakeOutgoingFrame(OutBuffer, &FrameLen,
410 Packet.Len[1] + 4, &Packet,
411 END_OF_ARGS);
413 // 5. Prepare and Fill MIC value
414 NdisZeroMemory(Mic, sizeof(Mic));
415 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
417 // AES
418 UCHAR digest[80];
420 HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
421 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
423 else
425 INT i;
426 DBGPRINT(RT_DEBUG_INFO, " PMK = ");
427 for (i = 0; i < 16; i++)
428 DBGPRINT(RT_DEBUG_INFO, "%2x-", pAdapter->PortCfg.PskKey.Key[i]);
430 DBGPRINT(RT_DEBUG_INFO, "\n PTK = ");
431 for (i = 0; i < 64; i++)
432 DBGPRINT(RT_DEBUG_INFO, "%2x-", pAdapter->PortCfg.PTK[i]);
433 DBGPRINT(RT_DEBUG_INFO, "\n FrameLen = %d\n", FrameLen);
435 hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
437 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
439 FrameLen = 0;
440 // Make Transmitting frame
441 MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
442 sizeof(EAPHEAD), EAPHEAD,
443 Packet.Len[1] + 4, &Packet,
444 END_OF_ARGS);
446 // Send using priority queue
447 MiniportMMRequest(pAdapter, OutBuffer, FrameLen);
449 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg1Action <-----\n");
453 ========================================================================
455 Routine Description:
456 Process Pairwise key 4-way handshaking
458 Arguments:
459 pAdapter Pointer to our adapter
460 Elem Message body
462 Return Value:
463 None
465 Note:
467 ========================================================================
469 VOID WpaPairMsg3Action(
470 IN PRTMP_ADAPTER pAdapter,
471 IN MLME_QUEUE_ELEM *Elem)
473 PHEADER_802_11 pHeader;
474 UCHAR *OutBuffer = NULL;
475 HEADER_802_11 Header_802_11;
476 NDIS_STATUS NStatus;
477 UCHAR AckRate = RATE_2;
478 USHORT AckDuration = 0;
479 ULONG FrameLen = 0;
480 UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
481 EAPOL_PACKET Packet;
482 PEAPOL_PACKET pMsg3;
483 PUCHAR pTmp;
484 UCHAR Mic[16], OldMic[16];
485 NDIS_802_11_KEY PeerKey;
488 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg3Action ----->\n");
490 pHeader = (PHEADER_802_11) Elem->Msg;
492 // Process message 3 frame.
493 pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
495 #ifdef BIG_ENDIAN
496 *(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)));
497 #endif
499 // 1. Verify RSN IE & cipher type match
500 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
502 if (pMsg3->KeyDesc.KeyInfo.KeyDescVer != 2)
503 return;
504 pTmp = (PUCHAR) &CipherWpaPskAes;
506 else // TKIP
508 if (pMsg3->KeyDesc.KeyInfo.KeyDescVer != 1)
509 return;
510 pTmp = (PUCHAR) &CipherWpaPskTkip;
513 // Fix compatibility issue, when AP append nonsense data after auth mode with different size.
514 // We should qualify this kind of RSN as acceptable
515 if (!NdisEqualMemory((PUCHAR) &pMsg3->KeyDesc.KeyData[2], pTmp + 2, CipherWpaPskTkipLen - 2))
517 DBGPRINT(RT_DEBUG_ERROR, " RSN IE mismatched msg 3 of 4-way handshake!!!!!!!!!! \n");
518 return;
520 else
521 DBGPRINT(RT_DEBUG_TRACE, " RSN IE matched in msg 3 of 4-way handshake!!!!!!!!!! \n");
523 #ifdef BIG_ENDIAN
524 *(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)));
525 #endif
527 // 2. Check MIC value
528 // Save the MIC and replace with zero
529 NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
530 NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
531 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
533 // AES
534 UCHAR digest[80];
536 HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Len[1] + 4, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
537 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
539 else
541 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Len[1] + 4, Mic);
544 if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
546 DBGPRINT(RT_DEBUG_ERROR, " MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n");
547 return;
549 else
550 DBGPRINT(RT_DEBUG_TRACE, " MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n");
552 // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
553 if (RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
554 return;
556 // Update new replay counter
557 NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
559 // 4. Double check ANonce
560 if (!NdisEqualMemory(pAdapter->PortCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
561 return;
563 // 5. Construct Message 4
564 // =====================================
565 // Use Priority Ring & MiniportMMRequest
566 // =====================================
567 pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
568 WpaMacHeaderInit(pAdapter, &Header_802_11, 0, &pAdapter->PortCfg.Bssid);
570 // ACK size is 14 include CRC, and its rate is based on real time information
571 AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
572 AckDuration = RTMPCalcDuration(pAdapter, AckRate, 14);
573 Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
575 // Zero message 4 body
576 NdisZeroMemory(&Packet, sizeof(Packet));
577 Packet.Version = EAPOL_VER;
578 Packet.Type = EAPOLKey;
579 Packet.Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
582 // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
584 Packet.KeyDesc.Type = RSN_KEY_DESC;
586 #ifdef BIG_ENDIAN
587 *(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pMsg3->KeyDesc.KeyInfo)));
588 #endif
590 // Key descriptor version and appropriate RSN IE
591 Packet.KeyDesc.KeyInfo.KeyDescVer = pMsg3->KeyDesc.KeyInfo.KeyDescVer;
593 // Key Type PeerKey
594 Packet.KeyDesc.KeyInfo.KeyType = 1;
596 // KeyMic field presented
597 Packet.KeyDesc.KeyInfo.KeyMic = 1;
599 // Key Replay count
600 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
601 #ifdef BIG_ENDIAN
602 *(USHORT *)&Packet.KeyDesc.KeyInfo = SWAP16(*(USHORT *)&Packet.KeyDesc.KeyInfo);
603 #endif
605 // Out buffer for transmitting message 4
606 NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer); //Get an unused nonpaged memory
607 if (NStatus != NDIS_STATUS_SUCCESS)
608 return;
610 // Prepare EAPOL frame for MIC calculation
611 // Be careful, only EAPOL frame is counted for MIC calculation
612 MakeOutgoingFrame(OutBuffer, &FrameLen,
613 Packet.Len[1] + 4, &Packet,
614 END_OF_ARGS);
616 // Prepare and Fill MIC value
617 NdisZeroMemory(Mic, sizeof(Mic));
618 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
620 // AES
621 UCHAR digest[80];
623 HMAC_SHA1(OutBuffer, FrameLen, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
624 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
626 else
628 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
630 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
632 FrameLen = 0;
634 // Make Transmitting frame
635 MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
636 sizeof(EAPHEAD), EAPHEAD,
637 Packet.Len[1] + 4, &Packet,
638 END_OF_ARGS);
640 // 6. Send Message 4 to authenticator
641 // Send using priority queue
642 MiniportMMRequest(pAdapter, OutBuffer, FrameLen);
644 // 7. Update PTK
645 NdisZeroMemory(&PeerKey, sizeof(PeerKey));
646 PeerKey.Length = sizeof(PeerKey);
647 PeerKey.KeyIndex = 0xe0000000;
648 PeerKey.KeyLength = 16;
649 NdisMoveMemory(PeerKey.BSSID, pAdapter->PortCfg.Bssid.Octet, 6);
650 NdisMoveMemory(&PeerKey.KeyRSC, pMsg3->KeyDesc.KeyRsc, LEN_KEY_DESC_RSC);
651 NdisMoveMemory(PeerKey.KeyMaterial, &pAdapter->PortCfg.PTK[32], 32);
652 // Call Add peer key function
653 RTMPWPAAddKeyProc(pAdapter, &PeerKey);
655 DBGPRINT(RT_DEBUG_TRACE, "WpaPairMsg3Action <-----\n");
660 ========================================================================
662 Routine Description:
663 Process Group key 2-way handshaking
665 Arguments:
666 pAdapter Pointer to our adapter
667 Elem Message body
669 Return Value:
670 None
672 Note:
674 ========================================================================
676 VOID WpaGroupMsg1Action(
677 IN PRTMP_ADAPTER pAdapter,
678 IN MLME_QUEUE_ELEM *Elem)
680 PHEADER_802_11 pHeader;
681 UCHAR *OutBuffer = NULL;
682 HEADER_802_11 Header_802_11;
683 NDIS_STATUS NStatus;
684 UCHAR AckRate = RATE_2;
685 USHORT AckDuration = 0;
686 ULONG FrameLen = 0;
687 UCHAR EAPHEAD[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,0x88,0x8e};
688 EAPOL_PACKET Packet;
689 PEAPOL_PACKET pGroup;
690 UCHAR Mic[16], OldMic[16];
691 UCHAR GTK[32], Key[32];
692 NDIS_802_11_KEY GroupKey;
695 DBGPRINT(RT_DEBUG_TRACE, "WpaGroupMsg1Action ----->\n");
697 pHeader = (PHEADER_802_11) Elem->Msg;
699 // Process Group message 1 frame.
700 pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
702 // 1. Verify Replay counter
703 // Check Replay Counter, it has to be larger than last one. No need to be exact one larger
704 if (RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAdapter->PortCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
705 return;
707 // Update new replay counter
708 NdisMoveMemory(pAdapter->PortCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
710 // 2. Verify MIC is valid
711 // Save the MIC and replace with zero
712 NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
713 NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
714 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
716 // AES
717 UCHAR digest[80];
719 HMAC_SHA1((PUCHAR) pGroup, pGroup->Len[1] + 4, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
720 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
722 else
724 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Len[1] + 4, Mic);
727 if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
729 DBGPRINT(RT_DEBUG_ERROR, " MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n");
730 return;
732 else
733 DBGPRINT(RT_DEBUG_TRACE, " MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n");
735 #ifdef BIG_ENDIAN
736 *(USHORT *)(&(pGroup->KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(pGroup->KeyDesc.KeyInfo)));
737 #endif
739 // 3. Decrypt GTK from Key Data
740 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
742 if (pGroup->KeyDesc.KeyInfo.KeyDescVer != 2)
743 return;
744 // Decrypt AES GTK
745 AES_GTK_KEY_UNWRAP(&pAdapter->PortCfg.PTK[16], GTK, pGroup->KeyDesc.KeyData);
747 else // TKIP
749 INT i;
751 if (pGroup->KeyDesc.KeyInfo.KeyDescVer != 1)
752 return;
753 // Decrypt TKIP GTK
754 // Construct 32 bytes RC4 Key
755 NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16);
756 NdisMoveMemory(&Key[16], &pAdapter->PortCfg.PTK[16], 16);
757 ARCFOUR_INIT(&pAdapter->PrivateInfo.WEPCONTEXT, Key, 32);
758 //discard first 256 bytes
759 for (i = 0; i < 256; i++)
760 ARCFOUR_BYTE(&pAdapter->PrivateInfo.WEPCONTEXT);
761 // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
762 ARCFOUR_DECRYPT(&pAdapter->PrivateInfo.WEPCONTEXT, GTK, pGroup->KeyDesc.KeyData, 32);
765 // 4. Construct Group Message 2
766 pAdapter->Sequence = ((pAdapter->Sequence) + 1) & (MAX_SEQ_NUMBER);
767 WpaMacHeaderInit(pAdapter, &Header_802_11, 1, &pAdapter->PortCfg.Bssid);
769 // ACK size is 14 include CRC, and its rate is based on real time information
770 AckRate = pAdapter->PortCfg.ExpectedACKRate[pAdapter->PortCfg.TxRate];
771 AckDuration = RTMPCalcDuration(pAdapter, AckRate, 14);
772 Header_802_11.Controlhead.Duration = pAdapter->PortCfg.Dsifs + AckDuration;
774 // Zero Group message 1 body
775 NdisZeroMemory(&Packet, sizeof(Packet));
776 Packet.Version = EAPOL_VER;
777 Packet.Type = EAPOLKey;
778 Packet.Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
781 // Group Message 2 as EAPOL-Key(1,0,0,0,G,0,0,MIC,0)
783 Packet.KeyDesc.Type = RSN_KEY_DESC;
785 // Key descriptor version and appropriate RSN IE
786 Packet.KeyDesc.KeyInfo.KeyDescVer = pGroup->KeyDesc.KeyInfo.KeyDescVer;
788 // Key Type Group key
789 Packet.KeyDesc.KeyInfo.KeyType = 0;
791 // KeyMic field presented
792 Packet.KeyDesc.KeyInfo.KeyMic = 1;
794 // Secure bit is 1
795 Packet.KeyDesc.KeyInfo.Secure = 1;
797 // Key Replay count
798 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
800 #ifdef BIG_ENDIAN
801 *(USHORT *)(&(Packet.KeyDesc.KeyInfo)) = SWAP16(*(USHORT *)(&(Packet.KeyDesc.KeyInfo)));
802 #endif
804 // Out buffer for transmitting group message 2
805 NStatus = MlmeAllocateMemory(pAdapter, (PVOID)&OutBuffer); //Get an unused nonpaged memory
806 if (NStatus != NDIS_STATUS_SUCCESS)
807 return;
809 // Prepare EAPOL frame for MIC calculation
810 // Be careful, only EAPOL frame is counted for MIC calculation
811 MakeOutgoingFrame(OutBuffer, &FrameLen,
812 Packet.Len[1] + 4, &Packet,
813 END_OF_ARGS);
815 // Prepare and Fill MIC value
816 NdisZeroMemory(Mic, sizeof(Mic));
817 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
819 // AES
820 UCHAR digest[80];
822 HMAC_SHA1(OutBuffer, FrameLen, pAdapter->PortCfg.PTK, LEN_EAP_MICK, digest);
823 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
825 else
827 INT i;
828 DBGPRINT(RT_DEBUG_INFO, "PTK = ");
829 for (i = 0; i < 64; i++)
830 DBGPRINT(RT_DEBUG_INFO, "%2x-", pAdapter->PortCfg.PTK[i]);
831 DBGPRINT(RT_DEBUG_INFO, "\n FrameLen = %d\n", FrameLen);
833 hmac_md5(pAdapter->PortCfg.PTK, LEN_EAP_MICK, OutBuffer, FrameLen, Mic);
835 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
837 FrameLen = 0;
838 // Make Transmitting frame
839 MakeOutgoingFrame(OutBuffer, &FrameLen, sizeof(MACHDR), &Header_802_11,
840 sizeof(EAPHEAD), EAPHEAD,
841 Packet.Len[1] + 4, &Packet,
842 END_OF_ARGS);
844 // 5. Copy frame to Tx ring and prepare for encryption
845 WpaHardEncrypt(pAdapter, OutBuffer, FrameLen);
847 // 6 Free allocated memory
848 MlmeFreeMemory(pAdapter, OutBuffer);
850 // 6. Update GTK
851 NdisZeroMemory(&GroupKey, sizeof(GroupKey));
852 GroupKey.Length = sizeof(GroupKey);
853 GroupKey.KeyIndex = 0x20000000 | pGroup->KeyDesc.KeyInfo.KeyIndex;
854 GroupKey.KeyLength = 16;
855 NdisMoveMemory(GroupKey.BSSID, pAdapter->PortCfg.Bssid.Octet, 6);
856 NdisMoveMemory(GroupKey.KeyMaterial, GTK, 32);
857 // Call Add peer key function
858 RTMPWPAAddKeyProc(pAdapter, &GroupKey);
860 DBGPRINT(RT_DEBUG_TRACE, "WpaGroupMsg1Action <-----\n");
863 ========================================================================
865 Routine Description:
866 Init WPA MAC header
868 Arguments:
869 pAdapter Pointer to our adapter
871 Return Value:
872 None
874 Note:
876 ========================================================================
878 VOID WpaMacHeaderInit(
879 IN PRTMP_ADAPTER pAd,
880 IN OUT PHEADER_802_11 Hdr,
881 IN UCHAR wep,
882 IN PMACADDR pAddr1)
884 NdisZeroMemory(Hdr, sizeof(HEADER_802_11));
885 Hdr->Controlhead.Frame.Type = BTYPE_DATA;
886 Hdr->Controlhead.Frame.ToDs = 1;
887 if (wep == 1)
888 Hdr->Controlhead.Frame.Wep = 1;
890 // Addr1: DA, Addr2: BSSID, Addr3: SA
891 COPY_MAC_ADDR(&Hdr->Controlhead.Addr1, pAddr1);
892 COPY_MAC_ADDR(&Hdr->Controlhead.Addr2, &pAd->CurrentAddress);
893 COPY_MAC_ADDR(&Hdr->Addr3, &pAd->PortCfg.Bssid);
894 Hdr->Sequence = pAd->Sequence;
898 ========================================================================
900 Routine Description:
901 Copy frame from waiting queue into relative ring buffer and set
902 appropriate ASIC register to kick hardware encryption before really
903 sent out to air.
905 Arguments:
906 pAdapter Pointer to our adapter
907 PNDIS_PACKET Pointer to outgoing Ndis frame
908 NumberOfFrag Number of fragment required
910 Return Value:
911 None
913 Note:
915 ========================================================================
917 VOID WpaHardEncrypt(
918 IN PRTMP_ADAPTER pAdapter,
919 IN PUCHAR pPacket,
920 IN ULONG Len)
922 UCHAR FrameGap;
923 PUCHAR pDest;
924 PUCHAR pSrc;
925 UCHAR CipherAlg = CIPHER_NONE;
926 PTXD_STRUC pTxD;
927 #ifdef BIG_ENDIAN
928 TXD_STRUC TxD;
929 PTXD_STRUC pDestTxD;
930 PUCHAR pOriginDest;
931 #endif
932 ULONG Iv16;
933 ULONG Iv32;
934 PWPA_KEY pWpaKey;
935 UCHAR RetryMode = SHORT_RETRY;
936 static UCHAR Priority[4] = {"\x00\x00\x00\x00"};
937 unsigned long IrqFlags;
939 // Make sure Tx ring resource won't be used by other threads
940 NdisAcquireSpinLock(&pAdapter->TxRingLock);
942 FrameGap = IFS_BACKOFF; // Default frame gap mode
944 // outgoing frame always wakeup PHY to prevent frame lost and
945 // turn off PSM bit to improve performance
946 if (pAdapter->PortCfg.Psm == PWR_SAVE)
948 MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
950 AsicForceWakeup(pAdapter);
952 pAdapter->TxRing[pAdapter->CurEncryptIndex].FrameType = BTYPE_DATA;
954 pSrc = pPacket; // Point to start of MSDU
956 pWpaKey = (PWPA_KEY) &pAdapter->PortCfg.PairwiseKey[0];
957 pWpaKey->Type = PAIRWISE_KEY;
958 if (pWpaKey == NULL)
960 // No pairwise key, this should not happen
961 NdisReleaseSpinLock(&pAdapter->TxRingLock);
962 return;
965 // Get the Tx Ring descriptor & Dma Buffer address
966 pDest = (PUCHAR) pAdapter->TxRing[pAdapter->CurEncryptIndex].va_data_addr;
967 #ifndef BIG_ENDIAN
968 pTxD = (PTXD_STRUC) pAdapter->TxRing[pAdapter->CurEncryptIndex].va_addr;
969 #else
970 pOriginDest = pDest;
971 pDestTxD = (PTXD_STRUC) pAdapter->TxRing[pAdapter->CurEncryptIndex].va_addr;
972 TxD = *pDestTxD;
973 pTxD = &TxD;
974 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
975 #endif
977 if ((pTxD->Owner == DESC_OWN_NIC) || (pTxD->CipherOwn == DESC_OWN_NIC))
979 // Descriptor owned by NIC. No descriptor avaliable
980 // This should not happen since caller guaranteed.
981 // Make sure to release Tx ring resource
982 pAdapter->RalinkCounters.TxRingErrCount++;
983 NdisReleaseSpinLock(&pAdapter->TxRingLock);
984 return;
986 if (pTxD->Valid == TRUE)
988 // Ndis packet of last round did not cleared.
989 // This should not happen since caller guaranteed.
990 // Make sure to release Tx ring resource
991 pTxD->Valid = FALSE;
993 #ifdef BIG_ENDIAN
994 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
995 *pDestTxD = TxD;
996 #endif
998 pAdapter->RalinkCounters.TxRingErrCount++;
999 NdisReleaseSpinLock(&pAdapter->TxRingLock);
1000 return;
1003 // Copy whole frame to Tx ring buffer
1004 NdisMoveMemory(pDest, pPacket, Len);
1005 pDest += Len;
1007 if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled)
1009 INT i;
1011 i = 0;
1012 // Prepare 8 bytes TKIP encapsulation for MPDU
1014 TKIP_IV tkipIv;
1016 tkipIv.IV16.field.rc0 = *(pWpaKey->TxTsc + 1);
1017 tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f;
1018 tkipIv.IV16.field.rc2 = *pWpaKey->TxTsc;
1019 tkipIv.IV16.field.CONTROL.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV
1020 tkipIv.IV16.field.CONTROL.field.KeyID = 0;
1021 tkipIv.IV32 = *(PULONG)(pWpaKey->TxTsc + 2);
1023 pTxD->Iv = tkipIv.IV16.word;
1025 *((PUCHAR) &pTxD->Eiv) = *((PUCHAR) &tkipIv.IV32 + 3);
1026 *((PUCHAR) &pTxD->Eiv + 1) = *((PUCHAR) &tkipIv.IV32 + 2);
1027 *((PUCHAR) &pTxD->Eiv + 2) = *((PUCHAR) &tkipIv.IV32 + 1);
1028 *((PUCHAR) &pTxD->Eiv + 3) = *((PUCHAR) &tkipIv.IV32);
1031 // Increase TxTsc value for next transmission
1032 while (++pWpaKey->TxTsc[i] == 0x0)
1034 i++;
1035 if (i == 6)
1036 break;
1039 // Set IV offset
1040 pTxD->IvOffset = LENGTH_802_11;
1042 // Copy TKey
1043 NdisMoveMemory(pTxD->Key, pWpaKey->Key, 16);
1045 // Set Cipher suite
1046 CipherAlg = CIPHER_TKIP;
1048 // Calculate MIC value
1049 // Init MIC value calculation and reset the message
1050 pAdapter->PrivateInfo.Tx.L = RTMPTkipGetUInt32(pWpaKey->TxMic);
1051 pAdapter->PrivateInfo.Tx.R = RTMPTkipGetUInt32(pWpaKey->TxMic + 4);
1052 pAdapter->PrivateInfo.Tx.nBytesInM = 0;
1053 pAdapter->PrivateInfo.Tx.M = 0;
1055 // DA & SA field
1056 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc + 4, 12);
1058 // Priority + 3 bytes of 0
1059 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, Priority, 4);
1061 pSrc += LENGTH_802_11;
1062 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc, Len - LENGTH_802_11);
1063 RTMPTkipGetMIC(&pAdapter->PrivateInfo.Tx);
1064 // Append MIC
1065 NdisMoveMemory(pDest, pAdapter->PrivateInfo.Tx.MIC, 8);
1066 Len += 8;
1067 // IV + EIV + ICV which ASIC added after encryption done
1068 Len += 12;
1070 else if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)
1072 INT i;
1073 PUCHAR pTmp;
1075 i = 0;
1076 pTmp = (PUCHAR) &Iv16;
1077 *pTmp = pWpaKey->TxTsc[0];
1078 *(pTmp + 1) = pWpaKey->TxTsc[1];
1079 *(pTmp + 2) = 0;
1080 *(pTmp + 3) = 0x20;
1082 Iv32 = *(PULONG)(&pWpaKey->TxTsc[2]);
1084 // Increase TxTsc value for next transmission
1085 while (++pWpaKey->TxTsc[i] == 0x0)
1087 i++;
1088 if (i == 6)
1089 break;
1092 // Copy IV
1093 NdisMoveMemory(&pTxD->Iv, &Iv16, 4);
1095 // Copy EIV
1096 NdisMoveMemory(&pTxD->Eiv, &Iv32, 4);
1098 // Set IV offset
1099 pTxD->IvOffset = LENGTH_802_11;
1101 // Copy TKey
1102 NdisMoveMemory(pTxD->Key, pWpaKey->Key, 16);
1104 // Set Cipher suite
1105 CipherAlg = CIPHER_AES;
1107 // IV + EIV + HW MIC
1108 Len += 16;
1111 #ifdef BIG_ENDIAN
1112 RTMPFrameEndianChange(pAdapter, pOriginDest, DIR_WRITE, FALSE);
1113 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1114 *pDestTxD = TxD;
1115 pTxD = pDestTxD;
1116 #endif
1118 RTMPWriteTxDescriptor(pTxD, TRUE, CipherAlg, TRUE, FALSE, FALSE, RetryMode, FrameGap,
1119 pAdapter->PortCfg.TxRate, 4, Len, pAdapter->PortCfg.TxPreambleInUsed, 0);
1121 // Increase & maintain Tx Ring Index
1122 pAdapter->CurEncryptIndex++;
1123 if (pAdapter->CurEncryptIndex >= TX_RING_SIZE)
1125 pAdapter->CurEncryptIndex = 0;
1127 pAdapter->RalinkCounters.EncryptCount++;
1129 // Kick Encrypt Control Register at the end of all ring buffer preparation
1130 RTMP_IO_WRITE32(pAdapter, SECCSR1, 0x1);
1132 // Make sure to release Tx ring resource
1133 NdisReleaseSpinLock(&pAdapter->TxRingLock);
1137 ========================================================================
1139 Routine Description:
1140 SHA1 function
1142 Arguments:
1144 Return Value:
1146 Note:
1148 ========================================================================
1150 VOID HMAC_SHA1(
1151 IN UCHAR *text,
1152 IN UINT text_len,
1153 IN UCHAR *key,
1154 IN UINT key_len,
1155 IN UCHAR *digest)
1157 SHA_CTX context;
1158 UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
1159 UCHAR k_opad[65]; /* outer padding - key XORd with opad */
1160 INT i;
1162 // if key is longer than 64 bytes reset it to key=SHA1(key)
1163 if (key_len > 64)
1165 SHA_CTX tctx;
1166 SHAInit(&tctx);
1167 SHAUpdate(&tctx, key, key_len);
1168 SHAFinal(&tctx, key);
1169 key_len = 20;
1171 NdisZeroMemory(k_ipad, sizeof(k_ipad));
1172 NdisZeroMemory(k_opad, sizeof(k_opad));
1173 NdisMoveMemory(k_ipad, key, key_len);
1174 NdisMoveMemory(k_opad, key, key_len);
1176 // XOR key with ipad and opad values
1177 for (i = 0; i < 64; i++)
1179 k_ipad[i] ^= 0x36;
1180 k_opad[i] ^= 0x5c;
1183 // perform inner SHA1
1184 SHAInit(&context); /* init context for 1st pass */
1185 SHAUpdate(&context, k_ipad, 64); /* start with inner pad */
1186 SHAUpdate(&context, text, text_len); /* then text of datagram */
1187 SHAFinal(&context, digest); /* finish up 1st pass */
1189 //perform outer SHA1
1190 SHAInit(&context); /* init context for 2nd pass */
1191 SHAUpdate(&context, k_opad, 64); /* start with outer pad */
1192 SHAUpdate(&context, digest, 20); /* then results of 1st hash */
1193 SHAFinal(&context, digest); /* finish up 2nd pass */
1197 ========================================================================
1199 Routine Description:
1200 PRF function
1202 Arguments:
1204 Return Value:
1206 Note:
1207 802.1i Annex F.9
1209 ========================================================================
1211 VOID PRF(
1212 IN UCHAR *key,
1213 IN INT key_len,
1214 IN UCHAR *prefix,
1215 IN INT prefix_len,
1216 IN UCHAR *data,
1217 IN INT data_len,
1218 OUT UCHAR *output,
1219 IN INT len)
1221 INT i;
1222 UCHAR input[1024];
1223 INT currentindex = 0;
1224 INT total_len;
1226 NdisMoveMemory(input, prefix, prefix_len);
1227 input[prefix_len] = 0;
1228 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1229 total_len = prefix_len + 1 + data_len;
1230 input[total_len] = 0;
1231 total_len++;
1232 for (i = 0; i < (len + 19) / 20; i++)
1234 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
1235 currentindex += 20;
1236 input[total_len - 1]++;
1241 ========================================================================
1243 Routine Description:
1244 Count TPTK from PMK
1246 Arguments:
1248 Return Value:
1249 Output Store the TPTK
1251 Note:
1253 ========================================================================
1255 VOID WpaCountPTK(
1256 IN UCHAR *PMK,
1257 IN UCHAR *ANonce,
1258 IN UCHAR *AA,
1259 IN UCHAR *SNonce,
1260 IN UCHAR *SA,
1261 OUT UCHAR *output,
1262 IN UINT len)
1264 UCHAR concatenation[76];
1265 UINT CurrPos = 0;
1266 UCHAR temp[32];
1267 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1268 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
1270 NdisZeroMemory(temp, sizeof(temp));
1272 // Get smaller address
1273 if (RTMPCompareMemory(SA, AA, 6) == 1)
1274 NdisMoveMemory(concatenation, AA, 6);
1275 else
1276 NdisMoveMemory(concatenation, SA, 6);
1277 CurrPos += 6;
1279 // Get larger address
1280 if (RTMPCompareMemory(SA, AA, 6) == 1)
1281 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1282 else
1283 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1284 CurrPos += 6;
1286 // Get smaller address
1287 if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1288 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1289 else
1290 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1291 CurrPos += 32;
1293 // Get larger address
1294 if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1295 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1296 else
1297 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1298 CurrPos += 32;
1300 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76 , output, len);
1304 ========================================================================
1306 Routine Description:
1307 Misc function to Generate random number
1309 Arguments:
1311 Return Value:
1313 Note:
1314 802.1i Annex F.9
1316 ========================================================================
1318 VOID GenRandom(
1319 IN PRTMP_ADAPTER pAd,
1320 OUT UCHAR *random)
1322 INT i, curr;
1323 UCHAR local[80], KeyCounter[32];
1324 UCHAR result[80];
1325 ULONG CurrentTime;
1326 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
1328 NdisZeroMemory(result, 80);
1329 NdisZeroMemory(local, 80);
1330 NdisZeroMemory(KeyCounter, 32);
1331 NdisMoveMemory(local, pAd->CurrentAddress, ETH_LENGTH_OF_ADDRESS);
1333 for (i = 0; i < 32; i++)
1335 curr = ETH_LENGTH_OF_ADDRESS;
1336 CurrentTime = jiffies;
1337 NdisMoveMemory(local, pAd->CurrentAddress, ETH_LENGTH_OF_ADDRESS);
1338 curr += ETH_LENGTH_OF_ADDRESS;
1339 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1340 curr += sizeof(CurrentTime);
1341 NdisMoveMemory(&local[curr], result, 32);
1342 curr += 32;
1343 NdisMoveMemory(&local[curr], &i, 2);
1344 curr += 2;
1345 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
1347 NdisMoveMemory(random, result, 32);
1351 ========================================================================
1353 Routine Description:
1354 Misc function to decrypt AES body
1356 Arguments:
1358 Return Value:
1360 Note:
1361 This function references to RFC 3394 for aes key unwrap algorithm.
1363 ========================================================================
1365 VOID AES_GTK_KEY_UNWRAP(
1366 IN UCHAR *key,
1367 OUT UCHAR *plaintext,
1368 IN UCHAR *ciphertext)
1370 UCHAR A[8], BIN[16], BOUT[16];
1371 UCHAR R1[8],R2[8];
1372 UCHAR xor;
1373 INT num_blocks = 2;
1374 INT j;
1375 aes_context aesctx;
1377 // Initialize
1378 // A = C[0]
1379 NdisMoveMemory(A, ciphertext, 8);
1380 // R1 = C1
1381 NdisMoveMemory(R1, &ciphertext[8], 8);
1382 // R2 = C2
1383 NdisMoveMemory(R2, &ciphertext[16], 8);
1385 aes_set_key(&aesctx, key, 128);
1387 for (j = 5; j >= 0; j--)
1389 xor = num_blocks * j + 2;
1390 NdisMoveMemory(BIN, A, 8);
1391 BIN[7] = A[7] ^ xor;
1392 NdisMoveMemory(&BIN[8], R2, 8);
1393 aes_decrypt(&aesctx, BIN, BOUT);
1394 NdisMoveMemory(A, &BOUT[0], 8);
1395 NdisMoveMemory(R2, &BOUT[8], 8);
1397 xor = num_blocks * j + 1;
1398 NdisMoveMemory(BIN, A, 8);
1399 BIN[7] = A[7] ^ xor;
1400 NdisMoveMemory(&BIN[8], R1, 8);
1401 aes_decrypt(&aesctx, BIN, BOUT);
1402 NdisMoveMemory(A, &BOUT[0], 8);
1403 NdisMoveMemory(R1, &BOUT[8], 8);
1406 // OUTPUT
1407 NdisMoveMemory(&plaintext[0], R1, 8);
1408 NdisMoveMemory(&plaintext[8], R2, 8);