~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/rt2860/sta/wpa.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
        Justin P. Mattock       11/07/2010              Fix typos
38
 
*/
39
 
#include "../rt_config.h"
40
 
 
41
 
void inc_byte_array(u8 * counter, int len);
42
 
 
43
 
/*
44
 
        ========================================================================
45
 
 
46
 
        Routine Description:
47
 
                Process MIC error indication and record MIC error timer.
48
 
 
49
 
        Arguments:
50
 
                pAd     Pointer to our adapter
51
 
                pWpaKey                 Pointer to the WPA key structure
52
 
 
53
 
        Return Value:
54
 
                None
55
 
 
56
 
        IRQL = DISPATCH_LEVEL
57
 
 
58
 
        Note:
59
 
 
60
 
        ========================================================================
61
 
*/
62
 
void RTMPReportMicError(struct rt_rtmp_adapter *pAd, struct rt_cipher_key *pWpaKey)
63
 
{
64
 
        unsigned long Now;
65
 
        u8 unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1 : 0);
66
 
 
67
 
        /* Record Last MIC error time and count */
68
 
        NdisGetSystemUpTime(&Now);
69
 
        if (pAd->StaCfg.MicErrCnt == 0) {
70
 
                pAd->StaCfg.MicErrCnt++;
71
 
                pAd->StaCfg.LastMicErrorTime = Now;
72
 
                NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
73
 
        } else if (pAd->StaCfg.MicErrCnt == 1) {
74
 
                if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) {
75
 
                        /* Update Last MIC error time, this did not violate two MIC errors within 60 seconds */
76
 
                        pAd->StaCfg.LastMicErrorTime = Now;
77
 
                } else {
78
 
 
79
 
                        if (pAd->CommonCfg.bWirelessEvent)
80
 
                                RTMPSendWirelessEvent(pAd,
81
 
                                                      IW_COUNTER_MEASURES_EVENT_FLAG,
82
 
                                                      pAd->MacTab.
83
 
                                                      Content[BSSID_WCID].Addr,
84
 
                                                      BSS0, 0);
85
 
 
86
 
                        pAd->StaCfg.LastMicErrorTime = Now;
87
 
                        /* Violate MIC error counts, MIC countermeasures kicks in */
88
 
                        pAd->StaCfg.MicErrCnt++;
89
 
                        /* We shall block all reception */
90
 
                        /* We shall clean all Tx ring and disassociate from AP after next EAPOL frame */
91
 
                        /* */
92
 
                        /* No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets */
93
 
                        /* if pAd->StaCfg.MicErrCnt greater than 2. */
94
 
                        /* */
95
 
                        /* RTMPRingCleanUp(pAd, QID_AC_BK); */
96
 
                        /* RTMPRingCleanUp(pAd, QID_AC_BE); */
97
 
                        /* RTMPRingCleanUp(pAd, QID_AC_VI); */
98
 
                        /* RTMPRingCleanUp(pAd, QID_AC_VO); */
99
 
                        /* RTMPRingCleanUp(pAd, QID_HCCA); */
100
 
                }
101
 
        } else {
102
 
                /* MIC error count >= 2 */
103
 
                /* This should not happen */
104
 
                ;
105
 
        }
106
 
        MlmeEnqueue(pAd,
107
 
                    MLME_CNTL_STATE_MACHINE,
108
 
                    OID_802_11_MIC_FAILURE_REPORT_FRAME, 1, &unicastKey);
109
 
 
110
 
        if (pAd->StaCfg.MicErrCnt == 2) {
111
 
                RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
112
 
        }
113
 
}
114
 
 
115
 
#define LENGTH_EAP_H    4
116
 
/* If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). */
117
 
int WpaCheckEapCode(struct rt_rtmp_adapter *pAd,
118
 
                    u8 *pFrame, u16 FrameLen, u16 OffSet)
119
 
{
120
 
 
121
 
        u8 *pData;
122
 
        int result = 0;
123
 
 
124
 
        if (FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H)
125
 
                return result;
126
 
 
127
 
        pData = pFrame + OffSet;        /* skip offset bytes */
128
 
 
129
 
        if (*(pData + 1) == EAPPacket)  /* 802.1x header - Packet Type */
130
 
        {
131
 
                result = *(pData + 4);  /* EAP header - Code */
132
 
        }
133
 
 
134
 
        return result;
135
 
}
136
 
 
137
 
void WpaSendMicFailureToWpaSupplicant(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUnicast)
138
 
{
139
 
        char custom[IW_CUSTOM_MAX] = { 0 };
140
 
 
141
 
        sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
142
 
        if (bUnicast)
143
 
                sprintf(custom, "%s unicast", custom);
144
 
 
145
 
        RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (u8 *)custom,
146
 
                                strlen(custom));
147
 
 
148
 
        return;
149
 
}
150
 
 
151
 
void WpaMicFailureReportFrame(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
152
 
{
153
 
        u8 *pOutBuffer = NULL;
154
 
        u8 Header802_3[14];
155
 
        unsigned long FrameLen = 0;
156
 
        struct rt_eapol_packet Packet;
157
 
        u8 Mic[16];
158
 
        BOOLEAN bUnicast;
159
 
 
160
 
        DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
161
 
 
162
 
        bUnicast = (Elem->Msg[0] == 1 ? TRUE : FALSE);
163
 
        pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
164
 
 
165
 
        /* init 802.3 header and Fill Packet */
166
 
        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid,
167
 
                          pAd->CurrentAddress, EAPOL);
168
 
 
169
 
        NdisZeroMemory(&Packet, sizeof(Packet));
170
 
        Packet.ProVer = EAPOL_VER;
171
 
        Packet.ProType = EAPOLKey;
172
 
 
173
 
        Packet.KeyDesc.Type = WPA1_KEY_DESC;
174
 
 
175
 
        /* Request field presented */
176
 
        Packet.KeyDesc.KeyInfo.Request = 1;
177
 
 
178
 
        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) {
179
 
                Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
180
 
        } else                  /* TKIP */
181
 
        {
182
 
                Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
183
 
        }
184
 
 
185
 
        Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
186
 
 
187
 
        /* KeyMic field presented */
188
 
        Packet.KeyDesc.KeyInfo.KeyMic = 1;
189
 
 
190
 
        /* Error field presented */
191
 
        Packet.KeyDesc.KeyInfo.Error = 1;
192
 
 
193
 
        /* Update packet length after decide Key data payload */
194
 
        SET_u16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG)
195
 
            /* Key Replay Count */
196
 
            NdisMoveMemory(Packet.KeyDesc.ReplayCounter,
197
 
                           pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
198
 
        inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
199
 
 
200
 
        /* Convert to little-endian format. */
201
 
        *((u16 *) & Packet.KeyDesc.KeyInfo) =
202
 
            cpu2le16(*((u16 *) & Packet.KeyDesc.KeyInfo));
203
 
 
204
 
        MlmeAllocateMemory(pAd, (u8 **) & pOutBuffer);  /* allocate memory */
205
 
        if (pOutBuffer == NULL) {
206
 
                return;
207
 
        }
208
 
        /* Prepare EAPOL frame for MIC calculation */
209
 
        /* Be careful, only EAPOL frame is counted for MIC calculation */
210
 
        MakeOutgoingFrame(pOutBuffer, &FrameLen,
211
 
                          CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, &Packet,
212
 
                          END_OF_ARGS);
213
 
 
214
 
        /* Prepare and Fill MIC value */
215
 
        NdisZeroMemory(Mic, sizeof(Mic));
216
 
        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) {    /* AES */
217
 
                u8 digest[20] = { 0 };
218
 
                HMAC_SHA1(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen,
219
 
                          digest, SHA1_DIGEST_SIZE);
220
 
                NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
221
 
        } else {                /* TKIP */
222
 
                HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen,
223
 
                         Mic, MD5_DIGEST_SIZE);
224
 
        }
225
 
        NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
226
 
 
227
 
        /* copy frame to Tx ring and send MIC failure report frame to authenticator */
228
 
        RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID],
229
 
                          Header802_3, LENGTH_802_3,
230
 
                          (u8 *)& Packet,
231
 
                          CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, FALSE);
232
 
 
233
 
        MlmeFreeMemory(pAd, (u8 *)pOutBuffer);
234
 
 
235
 
        DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
236
 
}
237
 
 
238
 
/** from wpa_supplicant
239
 
 * inc_byte_array - Increment arbitrary length byte array by one
240
 
 * @counter: Pointer to byte array
241
 
 * @len: Length of the counter in bytes
242
 
 *
243
 
 * This function increments the last byte of the counter by one and continues
244
 
 * rolling over to more significant bytes if the byte was incremented from
245
 
 * 0xff to 0x00.
246
 
 */
247
 
void inc_byte_array(u8 * counter, int len)
248
 
{
249
 
        int pos = len - 1;
250
 
        while (pos >= 0) {
251
 
                counter[pos]++;
252
 
                if (counter[pos] != 0)
253
 
                        break;
254
 
                pos--;
255
 
        }
256
 
}
257
 
 
258
 
void WpaDisassocApAndBlockAssoc(void *SystemSpecific1,
259
 
                                void *FunctionContext,
260
 
                                void *SystemSpecific2,
261
 
                                void *SystemSpecific3)
262
 
{
263
 
        struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
264
 
        struct rt_mlme_disassoc_req DisassocReq;
265
 
 
266
 
        /* disassoc from current AP first */
267
 
        DBGPRINT(RT_DEBUG_TRACE,
268
 
                 ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
269
 
        DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid,
270
 
                         REASON_MIC_FAILURE);
271
 
        MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
272
 
                    sizeof(struct rt_mlme_disassoc_req), &DisassocReq);
273
 
 
274
 
        pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
275
 
        pAd->StaCfg.bBlockAssoc = TRUE;
276
 
}
277
 
 
278
 
void WpaStaPairwiseKeySetting(struct rt_rtmp_adapter *pAd)
279
 
{
280
 
        struct rt_cipher_key *pSharedKey;
281
 
        struct rt_mac_table_entry *pEntry;
282
 
 
283
 
        pEntry = &pAd->MacTab.Content[BSSID_WCID];
284
 
 
285
 
        /* Pairwise key shall use key#0 */
286
 
        pSharedKey = &pAd->SharedKey[BSS0][0];
287
 
 
288
 
        NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
289
 
 
290
 
        /* Prepare pair-wise key information into shared key table */
291
 
        NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
292
 
        pSharedKey->KeyLen = LEN_TKIP_EK;
293
 
        NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
294
 
        NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
295
 
                       LEN_TKIP_RXMICK);
296
 
        NdisMoveMemory(pSharedKey->TxMic,
297
 
                       &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
298
 
 
299
 
        /* Decide its ChiperAlg */
300
 
        if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
301
 
                pSharedKey->CipherAlg = CIPHER_TKIP;
302
 
        else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
303
 
                pSharedKey->CipherAlg = CIPHER_AES;
304
 
        else
305
 
                pSharedKey->CipherAlg = CIPHER_NONE;
306
 
 
307
 
        /* Update these related information to struct rt_mac_table_entry */
308
 
        NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
309
 
                       LEN_TKIP_EK);
310
 
        NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
311
 
                       LEN_TKIP_RXMICK);
312
 
        NdisMoveMemory(pEntry->PairwiseKey.TxMic,
313
 
                       &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
314
 
        pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
315
 
 
316
 
        /* Update pairwise key information to ASIC Shared Key Table */
317
 
        AsicAddSharedKeyEntry(pAd,
318
 
                              BSS0,
319
 
                              0,
320
 
                              pSharedKey->CipherAlg,
321
 
                              pSharedKey->Key,
322
 
                              pSharedKey->TxMic, pSharedKey->RxMic);
323
 
 
324
 
        /* Update ASIC WCID attribute table and IVEIV table */
325
 
        RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pSharedKey->CipherAlg, pEntry);
326
 
        STA_PORT_SECURED(pAd);
327
 
        pAd->IndicateMediaState = NdisMediaStateConnected;
328
 
 
329
 
        DBGPRINT(RT_DEBUG_TRACE,
330
 
                 ("%s : AID(%d) port secured\n", __func__, pEntry->Aid));
331
 
 
332
 
}
333
 
 
334
 
void WpaStaGroupKeySetting(struct rt_rtmp_adapter *pAd)
335
 
{
336
 
        struct rt_cipher_key *pSharedKey;
337
 
 
338
 
        pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
339
 
 
340
 
        /* Prepare pair-wise key information into shared key table */
341
 
        NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
342
 
        pSharedKey->KeyLen = LEN_TKIP_EK;
343
 
        NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
344
 
        NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
345
 
                       LEN_TKIP_RXMICK);
346
 
        NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
347
 
                       LEN_TKIP_TXMICK);
348
 
 
349
 
        /* Update Shared Key CipherAlg */
350
 
        pSharedKey->CipherAlg = CIPHER_NONE;
351
 
        if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
352
 
                pSharedKey->CipherAlg = CIPHER_TKIP;
353
 
        else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
354
 
                pSharedKey->CipherAlg = CIPHER_AES;
355
 
        else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
356
 
                pSharedKey->CipherAlg = CIPHER_WEP64;
357
 
        else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
358
 
                pSharedKey->CipherAlg = CIPHER_WEP128;
359
 
 
360
 
        /* Update group key information to ASIC Shared Key Table */
361
 
        AsicAddSharedKeyEntry(pAd,
362
 
                              BSS0,
363
 
                              pAd->StaCfg.DefaultKeyId,
364
 
                              pSharedKey->CipherAlg,
365
 
                              pSharedKey->Key,
366
 
                              pSharedKey->TxMic, pSharedKey->RxMic);
367
 
 
368
 
        /* Update ASIC WCID attribute table and IVEIV table */
369
 
        RTMPAddWcidAttributeEntry(pAd,
370
 
                                  BSS0,
371
 
                                  pAd->StaCfg.DefaultKeyId,
372
 
                                  pSharedKey->CipherAlg, NULL);
373
 
 
374
 
}