]>
Commit | Line | Data |
---|---|---|
36c7928c BZ |
1 | /* |
2 | ************************************************************************* | |
3 | * Ralink Tech Inc. | |
4 | * 5F., No.36, Taiyuan St., Jhubei City, | |
5 | * Hsinchu County 302, | |
6 | * Taiwan, R.O.C. | |
7 | * | |
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify * | |
11 | * it under the terms of the GNU General Public License as published by * | |
12 | * the Free Software Foundation; either version 2 of the License, or * | |
13 | * (at your option) any later version. * | |
14 | * * | |
15 | * This program is distributed in the hope that it will be useful, * | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
18 | * GNU General Public License for more details. * | |
19 | * * | |
20 | * You should have received a copy of the GNU General Public License * | |
21 | * along with this program; if not, write to the * | |
22 | * Free Software Foundation, Inc., * | |
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |
24 | * * | |
25 | ************************************************************************* | |
26 | ||
27 | Module Name: | |
28 | wpa.c | |
29 | ||
30 | Abstract: | |
31 | ||
32 | Revision History: | |
33 | Who When What | |
34 | -------- ---------- ---------------------------------------------- | |
35 | Jan Lee 03-07-22 Initial | |
36 | Paul Lin 03-11-28 Modify for supplicant | |
37 | */ | |
38 | ||
39 | #include "../rt_config.h" | |
40 | ||
41 | ||
42 | void inc_byte_array(UCHAR *counter, int len); | |
43 | ||
44 | /* | |
45 | ======================================================================== | |
46 | ||
47 | Routine Description: | |
48 | Process MIC error indication and record MIC error timer. | |
49 | ||
50 | Arguments: | |
51 | pAd Pointer to our adapter | |
52 | pWpaKey Pointer to the WPA key structure | |
53 | ||
54 | Return Value: | |
55 | None | |
56 | ||
57 | IRQL = DISPATCH_LEVEL | |
58 | ||
59 | Note: | |
60 | ||
61 | ======================================================================== | |
62 | */ | |
63 | VOID RTMPReportMicError( | |
64 | IN PRTMP_ADAPTER pAd, | |
65 | IN PCIPHER_KEY pWpaKey) | |
66 | { | |
67 | ULONG Now; | |
68 | UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); | |
69 | ||
70 | // Record Last MIC error time and count | |
71 | NdisGetSystemUpTime(&Now); | |
72 | if (pAd->StaCfg.MicErrCnt == 0) | |
73 | { | |
74 | pAd->StaCfg.MicErrCnt++; | |
75 | pAd->StaCfg.LastMicErrorTime = Now; | |
76 | NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); | |
77 | } | |
78 | else if (pAd->StaCfg.MicErrCnt == 1) | |
79 | { | |
80 | if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) | |
81 | { | |
82 | // Update Last MIC error time, this did not violate two MIC errors within 60 seconds | |
83 | pAd->StaCfg.LastMicErrorTime = Now; | |
84 | } | |
85 | else | |
86 | { | |
87 | ||
88 | if (pAd->CommonCfg.bWirelessEvent) | |
89 | RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); | |
90 | ||
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 | |
96 | // | |
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. | |
99 | // | |
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); | |
105 | } | |
106 | } | |
107 | else | |
108 | { | |
109 | // MIC error count >= 2 | |
110 | // This should not happen | |
111 | ; | |
112 | } | |
113 | MlmeEnqueue(pAd, | |
114 | MLME_CNTL_STATE_MACHINE, | |
115 | OID_802_11_MIC_FAILURE_REPORT_FRAME, | |
116 | 1, | |
117 | &unicastKey); | |
118 | ||
119 | if (pAd->StaCfg.MicErrCnt == 2) | |
120 | { | |
121 | RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); | |
122 | } | |
123 | } | |
124 | ||
125 | ||
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)). | |
129 | INT WpaCheckEapCode( | |
130 | IN PRTMP_ADAPTER pAd, | |
131 | IN PUCHAR pFrame, | |
132 | IN USHORT FrameLen, | |
133 | IN USHORT OffSet) | |
134 | { | |
135 | ||
136 | PUCHAR pData; | |
137 | INT result = 0; | |
138 | ||
139 | if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) | |
140 | return result; | |
141 | ||
142 | pData = pFrame + OffSet; // skip offset bytes | |
143 | ||
144 | if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type | |
145 | { | |
146 | result = *(pData+4); // EAP header - Code | |
147 | } | |
148 | ||
149 | return result; | |
150 | } | |
151 | ||
152 | VOID WpaSendMicFailureToWpaSupplicant( | |
153 | IN PRTMP_ADAPTER pAd, | |
154 | IN BOOLEAN bUnicast) | |
155 | { | |
156 | char custom[IW_CUSTOM_MAX] = {0}; | |
157 | ||
158 | sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); | |
159 | if(bUnicast) | |
160 | sprintf(custom, "%s unicast", custom); | |
161 | ||
162 | RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (PUCHAR)custom, strlen(custom)); | |
163 | ||
164 | return; | |
165 | } | |
166 | #endif // WPA_SUPPLICANT_SUPPORT // | |
167 | ||
168 | VOID WpaMicFailureReportFrame( | |
169 | IN PRTMP_ADAPTER pAd, | |
170 | IN MLME_QUEUE_ELEM *Elem) | |
171 | { | |
172 | PUCHAR pOutBuffer = NULL; | |
173 | UCHAR Header802_3[14]; | |
174 | ULONG FrameLen = 0; | |
175 | EAPOL_PACKET Packet; | |
176 | UCHAR Mic[16]; | |
177 | BOOLEAN bUnicast; | |
178 | ||
179 | DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); | |
180 | ||
181 | bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); | |
182 | pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); | |
183 | ||
184 | // init 802.3 header and Fill Packet | |
185 | MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); | |
186 | ||
187 | NdisZeroMemory(&Packet, sizeof(Packet)); | |
188 | Packet.ProVer = EAPOL_VER; | |
189 | Packet.ProType = EAPOLKey; | |
190 | ||
191 | Packet.KeyDesc.Type = WPA1_KEY_DESC; | |
192 | ||
193 | // Request field presented | |
194 | Packet.KeyDesc.KeyInfo.Request = 1; | |
195 | ||
196 | if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) | |
197 | { | |
198 | Packet.KeyDesc.KeyInfo.KeyDescVer = 2; | |
199 | } | |
200 | else // TKIP | |
201 | { | |
202 | Packet.KeyDesc.KeyInfo.KeyDescVer = 1; | |
203 | } | |
204 | ||
205 | Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); | |
206 | ||
207 | // KeyMic field presented | |
208 | Packet.KeyDesc.KeyInfo.KeyMic = 1; | |
209 | ||
210 | // Error field presented | |
211 | Packet.KeyDesc.KeyInfo.Error = 1; | |
212 | ||
213 | // Update packet length after decide Key data payload | |
214 | SET_UINT16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG) | |
215 | ||
216 | // Key Replay Count | |
217 | NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); | |
218 | inc_byte_array(pAd->StaCfg.ReplayCounter, 8); | |
219 | ||
220 | // Convert to little-endian format. | |
221 | *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); | |
222 | ||
223 | ||
224 | MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory | |
225 | if(pOutBuffer == NULL) | |
226 | { | |
227 | return; | |
228 | } | |
229 | ||
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, | |
234 | END_OF_ARGS); | |
235 | ||
236 | // Prepare and Fill MIC value | |
237 | NdisZeroMemory(Mic, sizeof(Mic)); | |
238 | if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) | |
239 | { // AES | |
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); | |
243 | } | |
244 | else | |
245 | { // TKIP | |
246 | HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); | |
247 | } | |
248 | NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); | |
249 | ||
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, | |
253 | (PUCHAR)&Packet, | |
254 | CONV_ARRARY_TO_UINT16(Packet.Body_Len) + 4, FALSE); | |
255 | ||
256 | MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); | |
257 | ||
258 | DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); | |
259 | } | |
260 | ||
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 | |
265 | * | |
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 | |
268 | * 0xff to 0x00. | |
269 | */ | |
270 | void inc_byte_array(UCHAR *counter, int len) | |
271 | { | |
272 | int pos = len - 1; | |
273 | while (pos >= 0) { | |
274 | counter[pos]++; | |
275 | if (counter[pos] != 0) | |
276 | break; | |
277 | pos--; | |
278 | } | |
279 | } | |
280 | ||
281 | VOID WpaDisassocApAndBlockAssoc( | |
282 | IN PVOID SystemSpecific1, | |
283 | IN PVOID FunctionContext, | |
284 | IN PVOID SystemSpecific2, | |
285 | IN PVOID SystemSpecific3) | |
286 | { | |
287 | RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; | |
288 | MLME_DISASSOC_REQ_STRUCT DisassocReq; | |
289 | ||
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); | |
294 | ||
295 | pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; | |
296 | pAd->StaCfg.bBlockAssoc = TRUE; | |
297 | } | |
298 | ||
299 | VOID WpaStaPairwiseKeySetting( | |
300 | IN PRTMP_ADAPTER pAd) | |
301 | { | |
302 | PCIPHER_KEY pSharedKey; | |
303 | PMAC_TABLE_ENTRY pEntry; | |
304 | ||
305 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | |
306 | ||
307 | // Pairwise key shall use key#0 | |
308 | pSharedKey = &pAd->SharedKey[BSS0][0]; | |
309 | ||
310 | NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); | |
311 | ||
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); | |
318 | ||
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; | |
324 | else | |
325 | pSharedKey->CipherAlg = CIPHER_NONE; | |
326 | ||
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; | |
332 | ||
333 | // Update pairwise key information to ASIC Shared Key Table | |
334 | AsicAddSharedKeyEntry(pAd, | |
335 | BSS0, | |
336 | 0, | |
337 | pSharedKey->CipherAlg, | |
338 | pSharedKey->Key, | |
339 | pSharedKey->TxMic, | |
340 | pSharedKey->RxMic); | |
341 | ||
342 | // Update ASIC WCID attribute table and IVEIV table | |
343 | RTMPAddWcidAttributeEntry(pAd, | |
344 | BSS0, | |
345 | 0, | |
346 | pSharedKey->CipherAlg, | |
347 | pEntry); | |
348 | STA_PORT_SECURED(pAd); | |
349 | pAd->IndicateMediaState = NdisMediaStateConnected; | |
350 | ||
351 | DBGPRINT(RT_DEBUG_TRACE, ("%s : AID(%d) port secured\n", __FUNCTION__, pEntry->Aid)); | |
352 | ||
353 | } | |
354 | ||
355 | VOID WpaStaGroupKeySetting( | |
356 | IN PRTMP_ADAPTER pAd) | |
357 | { | |
358 | PCIPHER_KEY pSharedKey; | |
359 | ||
360 | pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; | |
361 | ||
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); | |
368 | ||
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; | |
379 | ||
380 | // Update group key information to ASIC Shared Key Table | |
381 | AsicAddSharedKeyEntry(pAd, | |
382 | BSS0, | |
383 | pAd->StaCfg.DefaultKeyId, | |
384 | pSharedKey->CipherAlg, | |
385 | pSharedKey->Key, | |
386 | pSharedKey->TxMic, | |
387 | pSharedKey->RxMic); | |
388 | ||
389 | // Update ASIC WCID attribute table and IVEIV table | |
390 | RTMPAddWcidAttributeEntry(pAd, | |
391 | BSS0, | |
392 | pAd->StaCfg.DefaultKeyId, | |
393 | pSharedKey->CipherAlg, | |
394 | NULL); | |
395 | ||
396 | } |