2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
39 #include "../rt_config.h"
42 void inc_byte_array(UCHAR
*counter
, int len
);
45 ========================================================================
48 Process MIC error indication and record MIC error timer.
51 pAd Pointer to our adapter
52 pWpaKey Pointer to the WPA key structure
61 ========================================================================
63 VOID
RTMPReportMicError(
65 IN PCIPHER_KEY pWpaKey
)
68 UCHAR unicastKey
= (pWpaKey
->Type
== PAIRWISE_KEY
? 1:0);
70 // Record Last MIC error time and count
71 NdisGetSystemUpTime(&Now
);
72 if (pAd
->StaCfg
.MicErrCnt
== 0)
74 pAd
->StaCfg
.MicErrCnt
++;
75 pAd
->StaCfg
.LastMicErrorTime
= Now
;
76 NdisZeroMemory(pAd
->StaCfg
.ReplayCounter
, 8);
78 else if (pAd
->StaCfg
.MicErrCnt
== 1)
80 if ((pAd
->StaCfg
.LastMicErrorTime
+ (60 * OS_HZ
)) < Now
)
82 // Update Last MIC error time, this did not violate two MIC errors within 60 seconds
83 pAd
->StaCfg
.LastMicErrorTime
= Now
;
88 if (pAd
->CommonCfg
.bWirelessEvent
)
89 RTMPSendWirelessEvent(pAd
, IW_COUNTER_MEASURES_EVENT_FLAG
, pAd
->MacTab
.Content
[BSSID_WCID
].Addr
, BSS0
, 0);
91 pAd
->StaCfg
.LastMicErrorTime
= Now
;
92 // Violate MIC error counts, MIC countermeasures kicks in
93 pAd
->StaCfg
.MicErrCnt
++;
94 // We shall block all reception
95 // We shall clean all Tx ring and disassoicate from AP after next EAPOL frame
97 // No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets
98 // if pAd->StaCfg.MicErrCnt greater than 2.
100 // RTMPRingCleanUp(pAd, QID_AC_BK);
101 // RTMPRingCleanUp(pAd, QID_AC_BE);
102 // RTMPRingCleanUp(pAd, QID_AC_VI);
103 // RTMPRingCleanUp(pAd, QID_AC_VO);
104 // RTMPRingCleanUp(pAd, QID_HCCA);
109 // MIC error count >= 2
110 // This should not happen
114 MLME_CNTL_STATE_MACHINE
,
115 OID_802_11_MIC_FAILURE_REPORT_FRAME
,
119 if (pAd
->StaCfg
.MicErrCnt
== 2)
121 RTMPSetTimer(&pAd
->StaCfg
.WpaDisassocAndBlockAssocTimer
, 100);
126 #ifdef WPA_SUPPLICANT_SUPPORT
127 #define LENGTH_EAP_H 4
128 // If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).
130 IN PRTMP_ADAPTER pAd
,
139 if( FrameLen
< OffSet
+ LENGTH_EAPOL_H
+ LENGTH_EAP_H
)
142 pData
= pFrame
+ OffSet
; // skip offset bytes
144 if(*(pData
+1) == EAPPacket
) // 802.1x header - Packet Type
146 result
= *(pData
+4); // EAP header - Code
152 VOID
WpaSendMicFailureToWpaSupplicant(
153 IN PRTMP_ADAPTER pAd
,
156 char custom
[IW_CUSTOM_MAX
] = {0};
158 sprintf(custom
, "MLME-MICHAELMICFAILURE.indication");
160 sprintf(custom
, "%s unicast", custom
);
162 RtmpOSWrielessEventSend(pAd
, IWEVCUSTOM
, -1, NULL
, (PUCHAR
)custom
, strlen(custom
));
166 #endif // WPA_SUPPLICANT_SUPPORT //
168 VOID
WpaMicFailureReportFrame(
169 IN PRTMP_ADAPTER pAd
,
170 IN MLME_QUEUE_ELEM
*Elem
)
172 PUCHAR pOutBuffer
= NULL
;
173 UCHAR Header802_3
[14];
179 DBGPRINT(RT_DEBUG_TRACE
, ("WpaMicFailureReportFrame ----->\n"));
181 bUnicast
= (Elem
->Msg
[0] == 1 ? TRUE
:FALSE
);
182 pAd
->Sequence
= ((pAd
->Sequence
) + 1) & (MAX_SEQ_NUMBER
);
184 // init 802.3 header and Fill Packet
185 MAKE_802_3_HEADER(Header802_3
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, EAPOL
);
187 NdisZeroMemory(&Packet
, sizeof(Packet
));
188 Packet
.ProVer
= EAPOL_VER
;
189 Packet
.ProType
= EAPOLKey
;
191 Packet
.KeyDesc
.Type
= WPA1_KEY_DESC
;
193 // Request field presented
194 Packet
.KeyDesc
.KeyInfo
.Request
= 1;
196 if(pAd
->StaCfg
.WepStatus
== Ndis802_11Encryption3Enabled
)
198 Packet
.KeyDesc
.KeyInfo
.KeyDescVer
= 2;
202 Packet
.KeyDesc
.KeyInfo
.KeyDescVer
= 1;
205 Packet
.KeyDesc
.KeyInfo
.KeyType
= (bUnicast
? PAIRWISEKEY
: GROUPKEY
);
207 // KeyMic field presented
208 Packet
.KeyDesc
.KeyInfo
.KeyMic
= 1;
210 // Error field presented
211 Packet
.KeyDesc
.KeyInfo
.Error
= 1;
213 // Update packet length after decide Key data payload
214 SET_UINT16_TO_ARRARY(Packet
.Body_Len
, LEN_EAPOL_KEY_MSG
)
217 NdisMoveMemory(Packet
.KeyDesc
.ReplayCounter
, pAd
->StaCfg
.ReplayCounter
, LEN_KEY_DESC_REPLAY
);
218 inc_byte_array(pAd
->StaCfg
.ReplayCounter
, 8);
220 // Convert to little-endian format.
221 *((USHORT
*)&Packet
.KeyDesc
.KeyInfo
) = cpu2le16(*((USHORT
*)&Packet
.KeyDesc
.KeyInfo
));
224 MlmeAllocateMemory(pAd
, (PUCHAR
*)&pOutBuffer
); // allocate memory
225 if(pOutBuffer
== NULL
)
230 // Prepare EAPOL frame for MIC calculation
231 // Be careful, only EAPOL frame is counted for MIC calculation
232 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
233 CONV_ARRARY_TO_UINT16(Packet
.Body_Len
) + 4, &Packet
,
236 // Prepare and Fill MIC value
237 NdisZeroMemory(Mic
, sizeof(Mic
));
238 if(pAd
->StaCfg
.WepStatus
== Ndis802_11Encryption3Enabled
)
240 UCHAR digest
[20] = {0};
241 HMAC_SHA1(pAd
->StaCfg
.PTK
, LEN_EAP_MICK
, pOutBuffer
, FrameLen
, digest
, SHA1_DIGEST_SIZE
);
242 NdisMoveMemory(Mic
, digest
, LEN_KEY_DESC_MIC
);
246 HMAC_MD5(pAd
->StaCfg
.PTK
, LEN_EAP_MICK
, pOutBuffer
, FrameLen
, Mic
, MD5_DIGEST_SIZE
);
248 NdisMoveMemory(Packet
.KeyDesc
.KeyMic
, Mic
, LEN_KEY_DESC_MIC
);
250 // copy frame to Tx ring and send MIC failure report frame to authenticator
251 RTMPToWirelessSta(pAd
, &pAd
->MacTab
.Content
[BSSID_WCID
],
252 Header802_3
, LENGTH_802_3
,
254 CONV_ARRARY_TO_UINT16(Packet
.Body_Len
) + 4, FALSE
);
256 MlmeFreeMemory(pAd
, (PUCHAR
)pOutBuffer
);
258 DBGPRINT(RT_DEBUG_TRACE
, ("WpaMicFailureReportFrame <-----\n"));
261 /** from wpa_supplicant
262 * inc_byte_array - Increment arbitrary length byte array by one
263 * @counter: Pointer to byte array
264 * @len: Length of the counter in bytes
266 * This function increments the last byte of the counter by one and continues
267 * rolling over to more significant bytes if the byte was incremented from
270 void inc_byte_array(UCHAR
*counter
, int len
)
275 if (counter
[pos
] != 0)
281 VOID
WpaDisassocApAndBlockAssoc(
282 IN PVOID SystemSpecific1
,
283 IN PVOID FunctionContext
,
284 IN PVOID SystemSpecific2
,
285 IN PVOID SystemSpecific3
)
287 RTMP_ADAPTER
*pAd
= (PRTMP_ADAPTER
)FunctionContext
;
288 MLME_DISASSOC_REQ_STRUCT DisassocReq
;
290 // disassoc from current AP first
291 DBGPRINT(RT_DEBUG_TRACE
, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
292 DisassocParmFill(pAd
, &DisassocReq
, pAd
->CommonCfg
.Bssid
, REASON_MIC_FAILURE
);
293 MlmeEnqueue(pAd
, ASSOC_STATE_MACHINE
, MT2_MLME_DISASSOC_REQ
, sizeof(MLME_DISASSOC_REQ_STRUCT
), &DisassocReq
);
295 pAd
->Mlme
.CntlMachine
.CurrState
= CNTL_WAIT_DISASSOC
;
296 pAd
->StaCfg
.bBlockAssoc
= TRUE
;
299 VOID
WpaStaPairwiseKeySetting(
300 IN PRTMP_ADAPTER pAd
)
302 PCIPHER_KEY pSharedKey
;
303 PMAC_TABLE_ENTRY pEntry
;
305 pEntry
= &pAd
->MacTab
.Content
[BSSID_WCID
];
307 // Pairwise key shall use key#0
308 pSharedKey
= &pAd
->SharedKey
[BSS0
][0];
310 NdisMoveMemory(pAd
->StaCfg
.PTK
, pEntry
->PTK
, LEN_PTK
);
312 // Prepare pair-wise key information into shared key table
313 NdisZeroMemory(pSharedKey
, sizeof(CIPHER_KEY
));
314 pSharedKey
->KeyLen
= LEN_TKIP_EK
;
315 NdisMoveMemory(pSharedKey
->Key
, &pAd
->StaCfg
.PTK
[32], LEN_TKIP_EK
);
316 NdisMoveMemory(pSharedKey
->RxMic
, &pAd
->StaCfg
.PTK
[48], LEN_TKIP_RXMICK
);
317 NdisMoveMemory(pSharedKey
->TxMic
, &pAd
->StaCfg
.PTK
[48+LEN_TKIP_RXMICK
], LEN_TKIP_TXMICK
);
319 // Decide its ChiperAlg
320 if (pAd
->StaCfg
.PairCipher
== Ndis802_11Encryption2Enabled
)
321 pSharedKey
->CipherAlg
= CIPHER_TKIP
;
322 else if (pAd
->StaCfg
.PairCipher
== Ndis802_11Encryption3Enabled
)
323 pSharedKey
->CipherAlg
= CIPHER_AES
;
325 pSharedKey
->CipherAlg
= CIPHER_NONE
;
327 // Update these related information to MAC_TABLE_ENTRY
328 NdisMoveMemory(pEntry
->PairwiseKey
.Key
, &pAd
->StaCfg
.PTK
[32], LEN_TKIP_EK
);
329 NdisMoveMemory(pEntry
->PairwiseKey
.RxMic
, &pAd
->StaCfg
.PTK
[48], LEN_TKIP_RXMICK
);
330 NdisMoveMemory(pEntry
->PairwiseKey
.TxMic
, &pAd
->StaCfg
.PTK
[48+LEN_TKIP_RXMICK
], LEN_TKIP_TXMICK
);
331 pEntry
->PairwiseKey
.CipherAlg
= pSharedKey
->CipherAlg
;
333 // Update pairwise key information to ASIC Shared Key Table
334 AsicAddSharedKeyEntry(pAd
,
337 pSharedKey
->CipherAlg
,
342 // Update ASIC WCID attribute table and IVEIV table
343 RTMPAddWcidAttributeEntry(pAd
,
346 pSharedKey
->CipherAlg
,
348 STA_PORT_SECURED(pAd
);
349 pAd
->IndicateMediaState
= NdisMediaStateConnected
;
351 DBGPRINT(RT_DEBUG_TRACE
, ("%s : AID(%d) port secured\n", __FUNCTION__
, pEntry
->Aid
));
355 VOID
WpaStaGroupKeySetting(
356 IN PRTMP_ADAPTER pAd
)
358 PCIPHER_KEY pSharedKey
;
360 pSharedKey
= &pAd
->SharedKey
[BSS0
][pAd
->StaCfg
.DefaultKeyId
];
362 // Prepare pair-wise key information into shared key table
363 NdisZeroMemory(pSharedKey
, sizeof(CIPHER_KEY
));
364 pSharedKey
->KeyLen
= LEN_TKIP_EK
;
365 NdisMoveMemory(pSharedKey
->Key
, pAd
->StaCfg
.GTK
, LEN_TKIP_EK
);
366 NdisMoveMemory(pSharedKey
->RxMic
, &pAd
->StaCfg
.GTK
[16], LEN_TKIP_RXMICK
);
367 NdisMoveMemory(pSharedKey
->TxMic
, &pAd
->StaCfg
.GTK
[24], LEN_TKIP_TXMICK
);
369 // Update Shared Key CipherAlg
370 pSharedKey
->CipherAlg
= CIPHER_NONE
;
371 if (pAd
->StaCfg
.GroupCipher
== Ndis802_11Encryption2Enabled
)
372 pSharedKey
->CipherAlg
= CIPHER_TKIP
;
373 else if (pAd
->StaCfg
.GroupCipher
== Ndis802_11Encryption3Enabled
)
374 pSharedKey
->CipherAlg
= CIPHER_AES
;
375 else if (pAd
->StaCfg
.GroupCipher
== Ndis802_11GroupWEP40Enabled
)
376 pSharedKey
->CipherAlg
= CIPHER_WEP64
;
377 else if (pAd
->StaCfg
.GroupCipher
== Ndis802_11GroupWEP104Enabled
)
378 pSharedKey
->CipherAlg
= CIPHER_WEP128
;
380 // Update group key information to ASIC Shared Key Table
381 AsicAddSharedKeyEntry(pAd
,
383 pAd
->StaCfg
.DefaultKeyId
,
384 pSharedKey
->CipherAlg
,
389 // Update ASIC WCID attribute table and IVEIV table
390 RTMPAddWcidAttributeEntry(pAd
,
392 pAd
->StaCfg
.DefaultKeyId
,
393 pSharedKey
->CipherAlg
,