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
38 #include "../rt_config.h"
40 void inc_byte_array(u8 * counter, int len);
43 ========================================================================
46 Process MIC error indication and record MIC error timer.
49 pAd Pointer to our adapter
50 pWpaKey Pointer to the WPA key structure
59 ========================================================================
61 void RTMPReportMicError(struct rt_rtmp_adapter *pAd, struct rt_cipher_key *pWpaKey)
64 u8 unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1 : 0);
66 /* Record Last MIC error time and count */
67 NdisGetSystemUpTime(&Now);
68 if (pAd->StaCfg.MicErrCnt == 0) {
69 pAd->StaCfg.MicErrCnt++;
70 pAd->StaCfg.LastMicErrorTime = Now;
71 NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
72 } else if (pAd->StaCfg.MicErrCnt == 1) {
73 if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) {
74 /* Update Last MIC error time, this did not violate two MIC errors within 60 seconds */
75 pAd->StaCfg.LastMicErrorTime = Now;
78 if (pAd->CommonCfg.bWirelessEvent)
79 RTMPSendWirelessEvent(pAd,
80 IW_COUNTER_MEASURES_EVENT_FLAG,
82 Content[BSSID_WCID].Addr,
85 pAd->StaCfg.LastMicErrorTime = Now;
86 /* Violate MIC error counts, MIC countermeasures kicks in */
87 pAd->StaCfg.MicErrCnt++;
88 /* We shall block all reception */
89 /* We shall clean all Tx ring and disassoicate from AP after next EAPOL frame */
91 /* No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets */
92 /* if pAd->StaCfg.MicErrCnt greater than 2. */
94 /* RTMPRingCleanUp(pAd, QID_AC_BK); */
95 /* RTMPRingCleanUp(pAd, QID_AC_BE); */
96 /* RTMPRingCleanUp(pAd, QID_AC_VI); */
97 /* RTMPRingCleanUp(pAd, QID_AC_VO); */
98 /* RTMPRingCleanUp(pAd, QID_HCCA); */
101 /* MIC error count >= 2 */
102 /* This should not happen */
106 MLME_CNTL_STATE_MACHINE,
107 OID_802_11_MIC_FAILURE_REPORT_FRAME, 1, &unicastKey);
109 if (pAd->StaCfg.MicErrCnt == 2) {
110 RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
114 #define LENGTH_EAP_H 4
115 /* If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). */
116 int WpaCheckEapCode(struct rt_rtmp_adapter *pAd,
117 u8 *pFrame, u16 FrameLen, u16 OffSet)
123 if (FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H)
126 pData = pFrame + OffSet; /* skip offset bytes */
128 if (*(pData + 1) == EAPPacket) /* 802.1x header - Packet Type */
130 result = *(pData + 4); /* EAP header - Code */
136 void WpaSendMicFailureToWpaSupplicant(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUnicast)
138 char custom[IW_CUSTOM_MAX] = { 0 };
140 sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
142 sprintf(custom, "%s unicast", custom);
144 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (u8 *)custom,
150 void WpaMicFailureReportFrame(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
152 u8 *pOutBuffer = NULL;
154 unsigned long FrameLen = 0;
155 struct rt_eapol_packet Packet;
159 DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
161 bUnicast = (Elem->Msg[0] == 1 ? TRUE : FALSE);
162 pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
164 /* init 802.3 header and Fill Packet */
165 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid,
166 pAd->CurrentAddress, EAPOL);
168 NdisZeroMemory(&Packet, sizeof(Packet));
169 Packet.ProVer = EAPOL_VER;
170 Packet.ProType = EAPOLKey;
172 Packet.KeyDesc.Type = WPA1_KEY_DESC;
174 /* Request field presented */
175 Packet.KeyDesc.KeyInfo.Request = 1;
177 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) {
178 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
181 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
184 Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
186 /* KeyMic field presented */
187 Packet.KeyDesc.KeyInfo.KeyMic = 1;
189 /* Error field presented */
190 Packet.KeyDesc.KeyInfo.Error = 1;
192 /* Update packet length after decide Key data payload */
193 SET_u16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG)
194 /* Key Replay Count */
195 NdisMoveMemory(Packet.KeyDesc.ReplayCounter,
196 pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
197 inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
199 /* Convert to little-endian format. */
200 *((u16 *) & Packet.KeyDesc.KeyInfo) =
201 cpu2le16(*((u16 *) & Packet.KeyDesc.KeyInfo));
203 MlmeAllocateMemory(pAd, (u8 **) & pOutBuffer); /* allocate memory */
204 if (pOutBuffer == NULL) {
207 /* Prepare EAPOL frame for MIC calculation */
208 /* Be careful, only EAPOL frame is counted for MIC calculation */
209 MakeOutgoingFrame(pOutBuffer, &FrameLen,
210 CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, &Packet,
213 /* Prepare and Fill MIC value */
214 NdisZeroMemory(Mic, sizeof(Mic));
215 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { /* AES */
216 u8 digest[20] = { 0 };
217 HMAC_SHA1(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen,
218 digest, SHA1_DIGEST_SIZE);
219 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
221 HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen,
222 Mic, MD5_DIGEST_SIZE);
224 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
226 /* copy frame to Tx ring and send MIC failure report frame to authenticator */
227 RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID],
228 Header802_3, LENGTH_802_3,
230 CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, FALSE);
232 MlmeFreeMemory(pAd, (u8 *)pOutBuffer);
234 DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
237 /** from wpa_supplicant
238 * inc_byte_array - Increment arbitrary length byte array by one
239 * @counter: Pointer to byte array
240 * @len: Length of the counter in bytes
242 * This function increments the last byte of the counter by one and continues
243 * rolling over to more significant bytes if the byte was incremented from
246 void inc_byte_array(u8 * counter, int len)
251 if (counter[pos] != 0)
257 void WpaDisassocApAndBlockAssoc(void *SystemSpecific1,
258 void *FunctionContext,
259 void *SystemSpecific2,
260 void *SystemSpecific3)
262 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
263 struct rt_mlme_disassoc_req DisassocReq;
265 /* disassoc from current AP first */
266 DBGPRINT(RT_DEBUG_TRACE,
267 ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
268 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid,
270 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
271 sizeof(struct rt_mlme_disassoc_req), &DisassocReq);
273 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
274 pAd->StaCfg.bBlockAssoc = TRUE;
277 void WpaStaPairwiseKeySetting(struct rt_rtmp_adapter *pAd)
279 struct rt_cipher_key *pSharedKey;
280 struct rt_mac_table_entry *pEntry;
282 pEntry = &pAd->MacTab.Content[BSSID_WCID];
284 /* Pairwise key shall use key#0 */
285 pSharedKey = &pAd->SharedKey[BSS0][0];
287 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
289 /* Prepare pair-wise key information into shared key table */
290 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
291 pSharedKey->KeyLen = LEN_TKIP_EK;
292 NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
293 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
295 NdisMoveMemory(pSharedKey->TxMic,
296 &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
298 /* Decide its ChiperAlg */
299 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
300 pSharedKey->CipherAlg = CIPHER_TKIP;
301 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
302 pSharedKey->CipherAlg = CIPHER_AES;
304 pSharedKey->CipherAlg = CIPHER_NONE;
306 /* Update these related information to struct rt_mac_table_entry */
307 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
309 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
311 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
312 &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
313 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
315 /* Update pairwise key information to ASIC Shared Key Table */
316 AsicAddSharedKeyEntry(pAd,
319 pSharedKey->CipherAlg,
321 pSharedKey->TxMic, pSharedKey->RxMic);
323 /* Update ASIC WCID attribute table and IVEIV table */
324 RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pSharedKey->CipherAlg, pEntry);
325 STA_PORT_SECURED(pAd);
326 pAd->IndicateMediaState = NdisMediaStateConnected;
328 DBGPRINT(RT_DEBUG_TRACE,
329 ("%s : AID(%d) port secured\n", __func__, pEntry->Aid));
333 void WpaStaGroupKeySetting(struct rt_rtmp_adapter *pAd)
335 struct rt_cipher_key *pSharedKey;
337 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
339 /* Prepare pair-wise key information into shared key table */
340 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
341 pSharedKey->KeyLen = LEN_TKIP_EK;
342 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
343 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
345 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
348 /* Update Shared Key CipherAlg */
349 pSharedKey->CipherAlg = CIPHER_NONE;
350 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
351 pSharedKey->CipherAlg = CIPHER_TKIP;
352 else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
353 pSharedKey->CipherAlg = CIPHER_AES;
354 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
355 pSharedKey->CipherAlg = CIPHER_WEP64;
356 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
357 pSharedKey->CipherAlg = CIPHER_WEP128;
359 /* Update group key information to ASIC Shared Key Table */
360 AsicAddSharedKeyEntry(pAd,
362 pAd->StaCfg.DefaultKeyId,
363 pSharedKey->CipherAlg,
365 pSharedKey->TxMic, pSharedKey->RxMic);
367 /* Update ASIC WCID attribute table and IVEIV table */
368 RTMPAddWcidAttributeEntry(pAd,
370 pAd->StaCfg.DefaultKeyId,
371 pSharedKey->CipherAlg, NULL);