MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / net / wireless / rtlink / rtmp_tkip.c
blobc322b1fcc36da52a79725eb2d68ffa582db8119d
1 /*************************************************************************
2 * Ralink Tech Inc. *
3 * 4F, No. 2 Technology 5th Rd. *
4 * Science-based Industrial Park *
5 * Hsin-chu, Taiwan, R.O.C. *
6 * *
7 * (c) Copyright 2002, Ralink Technology, Inc. *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program; if not, write to the *
21 * Free Software Foundation, Inc., *
22 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23 * *
24 *************************************************************************
26 Module Name:
27 rtmp_tkip.c
29 Abstract:
31 Revision History:
32 Who When What
33 -------- ---------- ----------------------------------------------
34 Paul Wu 02-25-02 Initial
37 #include "rt_config.h"
39 // Rotation functions on 32 bit values
40 #define ROL32( A, n ) ( ((A) << (n)) | ( ((A)>>(32-(n))) ) )
41 #define ROR32( A, n ) ROL32( (A), 32-(n) )
44 ========================================================================
46 Routine Description:
47 Convert from UCHAR[] to ULONG in a portable way
49 Arguments:
50 pMICKey pointer to MIC Key
52 Return Value:
53 None
55 Note:
57 ========================================================================
59 ULONG RTMPTkipGetUInt32(
60 IN PUCHAR pMICKey)
62 ULONG res = 0;
63 int i;
65 for (i = 0; i < 4; i++)
67 res |= (*pMICKey++) << (8 * i);
70 return res;
74 ========================================================================
76 Routine Description:
77 Convert from ULONG to UCHAR[] in a portable way
79 Arguments:
80 pDst pointer to destination for convert ULONG to UCHAR[]
81 val the value for convert
83 Return Value:
84 None
86 Note:
88 ========================================================================
90 VOID RTMPTkipPutUInt32(
91 IN OUT PUCHAR pDst,
92 IN ULONG val)
94 int i;
96 for(i = 0; i < 4; i++)
98 *pDst++ = (UCHAR) val;
99 val >>= 8;
104 ========================================================================
106 Routine Description:
107 Calculate the MIC Value.
109 Arguments:
110 pAdapter Pointer to our adapter
111 pSrc Pointer to source data for Calculate MIC Value
112 Len Indicate the length of the source data
114 Return Value:
115 None
117 Note:
119 ========================================================================
121 VOID RTMPTkipAppend(
122 IN PTKIP_KEY_INFO pTkip,
123 IN PUCHAR pSrc,
124 IN UINT nBytes)
126 register ULONG M, L, R, nBytesInM;
128 // load data from memory to register
129 L = pTkip->L;
130 R = pTkip->R;
131 nBytesInM = pTkip->nBytesInM;
132 M = pTkip->M;
134 // Alignment case
135 if((nBytesInM == 0) && ((((unsigned long)pSrc) & 0x3) == 0))
137 while(nBytes >= 4)
139 #ifdef BIG_ENDIAN
140 M = SWAP32(*(ULONG *)pSrc);
141 #else
142 M = *(ULONG *)pSrc;
143 #endif
144 pSrc += 4;
145 nBytes -= 4;
147 L ^= M;
148 R ^= ROL32( L, 17 );
149 L += R;
150 R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8);
151 L += R;
152 R ^= ROL32( L, 3 );
153 L += R;
154 R ^= ROR32( L, 2 );
155 L += R;
157 nBytesInM = 0;
158 M = 0;
160 while(nBytes > 0)
162 M |= (*pSrc << (8* nBytesInM));
164 nBytesInM++;
165 pSrc++;
166 nBytes--;
168 if( nBytesInM >= 4 )
170 L ^= M;
171 R ^= ROL32( L, 17 );
172 L += R;
173 R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8);
174 L += R;
175 R ^= ROL32( L, 3 );
176 L += R;
177 R ^= ROR32( L, 2 );
178 L += R;
179 // Clear the buffer
180 M = 0;
181 nBytesInM = 0;
185 else
186 { // misAlignment case
187 while(nBytes > 0)
189 M |= (*pSrc << (8* nBytesInM));
190 nBytesInM++;
192 pSrc++;
193 nBytes--;
195 if( nBytesInM >= 4 )
197 L ^= M;
198 R ^= ROL32( L, 17 );
199 L += R;
200 R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8);
201 L += R;
202 R ^= ROL32( L, 3 );
203 L += R;
204 R ^= ROR32( L, 2 );
205 L += R;
206 // Clear the buffer
207 M = 0;
208 nBytesInM = 0;
213 // load data from register to memory
214 pTkip->M = M;
215 pTkip->nBytesInM = nBytesInM;
216 pTkip->L = L;
217 pTkip->R = R;
221 ========================================================================
223 Routine Description:
224 Get the MIC Value.
226 Arguments:
227 pAdapter Pointer to our adapter
229 Return Value:
230 None
232 Note:
233 the MIC Value is store in pAdapter->PrivateInfo.MIC
234 ========================================================================
236 VOID RTMPTkipGetMIC(
237 IN PTKIP_KEY_INFO pTkip)
239 static unsigned char Last[] = {"\x5a\x00\x00\x00\x00\x00\x00\x00"};
241 // Append the minimum padding
242 RTMPTkipAppend(pTkip, Last, 8 - pTkip->nBytesInM);
244 // The appendByte function has already computed the result.
245 RTMPTkipPutUInt32(pTkip->MIC, pTkip->L);
246 RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R);
250 ========================================================================
252 Routine Description:
253 Compare MIC value of received MSDU
255 Arguments:
256 pAdapter Pointer to our adapter
257 pSrc Pointer to the received Plain text data
258 pDA Pointer to DA address
259 pSA Pointer to SA address
260 pMICKey pointer to MIC Key
261 Len the length of the received plain text data exclude MIC value
263 Return Value:
264 TRUE MIC value matched
265 FALSE MIC value mismatched
267 Note:
269 ========================================================================
271 BOOLEAN RTMPTkipCompareMICValue(
272 IN PRTMP_ADAPTER pAdapter,
273 IN PUCHAR pSrc,
274 IN PUCHAR pDA,
275 IN PUCHAR pSA,
276 IN PUCHAR pMICKey,
277 IN UINT Len)
279 static UCHAR Priority[4] = {"\x00\x00\x00\x00"};
281 // Init MIC value calculation and reset the message
282 pAdapter->PrivateInfo.Rx.L = RTMPTkipGetUInt32(pMICKey);
283 pAdapter->PrivateInfo.Rx.R = RTMPTkipGetUInt32(pMICKey + 4);
284 pAdapter->PrivateInfo.Rx.nBytesInM = 0;
285 pAdapter->PrivateInfo.Rx.M = 0;
287 // DA
288 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pDA, 6);
289 // SA
290 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pSA, 6);
291 // Priority + 3 bytes of 0
292 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, Priority, 4);
294 // Calculate MIC value from plain text data
295 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pSrc, Len);
297 // Get MIC value from decrypted plain data
298 RTMPTkipGetMIC(&pAdapter->PrivateInfo.Rx);
300 // Move MIC value from MSDU, this steps should move to data path.
301 // Since the MIC value might cross MPDUs.
302 if(!NdisEqualMemory(pAdapter->PrivateInfo.Rx.MIC, pSrc + Len, 8))
304 INT i;
306 DBGPRINT(RT_DEBUG_ERROR, "! TKIP MIC Error !\n"); //MIC error.
307 DBGPRINT(RT_DEBUG_INFO, "Orig MIC value ="); //MIC error.
308 for (i = 0; i < 8; i++)
310 DBGPRINT(RT_DEBUG_INFO, "%02x:", *(UCHAR*)(pSrc + Len + i)); //MIC error.
312 DBGPRINT(RT_DEBUG_INFO, "\n"); //MIC error.
313 DBGPRINT(RT_DEBUG_INFO, "Calculated MIC value ="); //MIC error.
314 for (i = 0; i < 8; i++)
316 DBGPRINT(RT_DEBUG_INFO, "%02x:", pAdapter->PrivateInfo.Rx.MIC[i]); //MIC error.
318 DBGPRINT(RT_DEBUG_INFO, "\n"); //MIC error.
319 return (FALSE);
321 return (TRUE);
325 ========================================================================
327 Routine Description:
328 Compare MIC value of received MSDU
330 Arguments:
331 pAdapter Pointer to our adapter
332 pLLC LLC header
333 pSrc Pointer to the received Plain text data
334 pDA Pointer to DA address
335 pSA Pointer to SA address
336 pMICKey pointer to MIC Key
337 Len the length of the received plain text data exclude MIC value
339 Return Value:
340 TRUE MIC value matched
341 FALSE MIC value mismatched
343 Note:
345 ========================================================================
347 BOOLEAN RTMPTkipCompareMICValueWithLLC(
348 IN PRTMP_ADAPTER pAdapter,
349 IN PUCHAR pLLC,
350 IN PUCHAR pSrc,
351 IN PUCHAR pDA,
352 IN PUCHAR pSA,
353 IN PUCHAR pMICKey,
354 IN UINT Len)
356 static UCHAR Priority[4] = {"\x00\x00\x00\x00"};
358 // Init MIC value calculation and reset the message
359 pAdapter->PrivateInfo.Rx.L = RTMPTkipGetUInt32(pMICKey);
360 pAdapter->PrivateInfo.Rx.R = RTMPTkipGetUInt32(pMICKey + 4);
361 pAdapter->PrivateInfo.Rx.nBytesInM = 0;
362 pAdapter->PrivateInfo.Rx.M = 0;
364 // DA
365 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pDA, 6);
366 // SA
367 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pSA, 6);
368 // Priority + 3 bytes of 0
369 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, Priority, 4);
371 // Start with LLC header
372 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pLLC, 8);
374 // Calculate MIC value from plain text data
375 RTMPTkipAppend(&pAdapter->PrivateInfo.Rx, pSrc, Len);
377 // Get MIC value from decrypted plain data
378 RTMPTkipGetMIC(&pAdapter->PrivateInfo.Rx);
380 // Move MIC value from MSDU, this steps should move to data path.
381 // Since the MIC value might cross MPDUs.
382 if(!NdisEqualMemory(pAdapter->PrivateInfo.Rx.MIC, pSrc + Len, 8))
384 INT i;
386 DBGPRINT(RT_DEBUG_ERROR, "! TKIP MIC Error !\n"); //MIC error.
387 DBGPRINT(RT_DEBUG_INFO, "Orig MIC value ="); //MIC error.
388 for (i = 0; i < 8; i++)
390 DBGPRINT(RT_DEBUG_INFO, "%02x:", *(UCHAR *)(pSrc + Len + i)); //MIC error.
393 DBGPRINT(RT_DEBUG_INFO, "\n"); //MIC error.
394 DBGPRINT(RT_DEBUG_INFO, "Calculated MIC value ="); //MIC error.
395 for (i = 0; i < 8; i++)
397 DBGPRINT(RT_DEBUG_INFO, "%02x:", pAdapter->PrivateInfo.Rx.MIC[i]); //MIC error.
400 DBGPRINT(RT_DEBUG_INFO, "\n"); //MIC error.
401 return (FALSE);
403 return (TRUE);
407 ========================================================================
409 Routine Description:
410 Copy frame from waiting queue into relative ring buffer and set
411 appropriate ASIC register to kick hardware transmit function
413 Arguments:
414 pAdapter Pointer to our adapter
415 PNDIS_PACKET Pointer to Ndis Packet for MIC calculation
416 pEncap Pointer to LLC encap data
417 LenEncap Total encap length, might be 0 which indicates no encap
419 Return Value:
420 None
422 Note:
424 ========================================================================
426 VOID RTMPCalculateMICValue(
427 IN PRTMP_ADAPTER pAdapter,
428 IN struct sk_buff *skb,
429 IN PUCHAR pEncap,
430 IN INT LenEncap,
431 IN PWPA_KEY pWpaKey)
433 PUCHAR pSrc;
434 static UCHAR Priority[4] = {"\x00\x00\x00\x00"};
436 pSrc = (PUCHAR) skb->data;
438 // Init MIC value calculation and reset the message
439 pAdapter->PrivateInfo.Tx.L = RTMPTkipGetUInt32(pWpaKey->TxMic);
440 pAdapter->PrivateInfo.Tx.R = RTMPTkipGetUInt32(pWpaKey->TxMic + 4);
441 pAdapter->PrivateInfo.Tx.nBytesInM = 0;
442 pAdapter->PrivateInfo.Tx.M = 0;
444 // DA & SA field
445 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc, 12);
447 // Priority + 3 bytes of 0
448 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, Priority, 4);
450 if (LenEncap > 0)
452 // LLC encapsulation
453 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pEncap, LenEncap);
454 // Protocol Type
455 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc + 12, skb->len - 12);
457 else
458 RTMPTkipAppend(&pAdapter->PrivateInfo.Tx, pSrc + 14, skb->len - 14);
460 // Compute the final MIC Value
461 RTMPTkipGetMIC(&pAdapter->PrivateInfo.Tx);