Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/xscaleiop
[deliverable/linux.git] / drivers / staging / rt2860 / common / cmm_wpa.c
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 #include "../rt_config.h"
39 // WPA OUI
40 UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00};
41 UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01};
42 UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01};
43 UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
44 UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
45 UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05};
46 UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
47 UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
48 // WPA2 OUI
49 UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
50 UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
51 UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
52 UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
53 UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
54 UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05};
55 // MSA OUI
56 UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06
57 UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06
58
59 /*
60 ========================================================================
61
62 Routine Description:
63 The pseudo-random function(PRF) that hashes various inputs to
64 derive a pseudo-random value. To add liveness to the pseudo-random
65 value, a nonce should be one of the inputs.
66
67 It is used to generate PTK, GTK or some specific random value.
68
69 Arguments:
70 UCHAR *key, - the key material for HMAC_SHA1 use
71 INT key_len - the length of key
72 UCHAR *prefix - a prefix label
73 INT prefix_len - the length of the label
74 UCHAR *data - a specific data with variable length
75 INT data_len - the length of a specific data
76 INT len - the output lenght
77
78 Return Value:
79 UCHAR *output - the calculated result
80
81 Note:
82 802.11i-2004 Annex H.3
83
84 ========================================================================
85 */
86 VOID PRF(
87 IN UCHAR *key,
88 IN INT key_len,
89 IN UCHAR *prefix,
90 IN INT prefix_len,
91 IN UCHAR *data,
92 IN INT data_len,
93 OUT UCHAR *output,
94 IN INT len)
95 {
96 INT i;
97 UCHAR *input;
98 INT currentindex = 0;
99 INT total_len;
100
101 // Allocate memory for input
102 os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
103
104 if (input == NULL)
105 {
106 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
107 return;
108 }
109
110 // Generate concatenation input
111 NdisMoveMemory(input, prefix, prefix_len);
112
113 // Concatenate a single octet containing 0
114 input[prefix_len] = 0;
115
116 // Concatenate specific data
117 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
118 total_len = prefix_len + 1 + data_len;
119
120 // Concatenate a single octet containing 0
121 // This octet shall be update later
122 input[total_len] = 0;
123 total_len++;
124
125 // Iterate to calculate the result by hmac-sha-1
126 // Then concatenate to last result
127 for (i = 0; i < (len + 19) / 20; i++)
128 {
129 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
130 currentindex += 20;
131
132 // update the last octet
133 input[total_len - 1]++;
134 }
135 os_free_mem(NULL, input);
136 }
137
138 /*
139 ========================================================================
140
141 Routine Description:
142 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
143 It shall be called by 4-way handshake processing.
144
145 Arguments:
146 pAd - pointer to our pAdapter context
147 PMK - pointer to PMK
148 ANonce - pointer to ANonce
149 AA - pointer to Authenticator Address
150 SNonce - pointer to SNonce
151 SA - pointer to Supplicant Address
152 len - indicate the length of PTK (octet)
153
154 Return Value:
155 Output pointer to the PTK
156
157 Note:
158 Refer to IEEE 802.11i-2004 8.5.1.2
159
160 ========================================================================
161 */
162 VOID WpaCountPTK(
163 IN PRTMP_ADAPTER pAd,
164 IN UCHAR *PMK,
165 IN UCHAR *ANonce,
166 IN UCHAR *AA,
167 IN UCHAR *SNonce,
168 IN UCHAR *SA,
169 OUT UCHAR *output,
170 IN UINT len)
171 {
172 UCHAR concatenation[76];
173 UINT CurrPos = 0;
174 UCHAR temp[32];
175 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
176 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
177
178 // initiate the concatenation input
179 NdisZeroMemory(temp, sizeof(temp));
180 NdisZeroMemory(concatenation, 76);
181
182 // Get smaller address
183 if (RTMPCompareMemory(SA, AA, 6) == 1)
184 NdisMoveMemory(concatenation, AA, 6);
185 else
186 NdisMoveMemory(concatenation, SA, 6);
187 CurrPos += 6;
188
189 // Get larger address
190 if (RTMPCompareMemory(SA, AA, 6) == 1)
191 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
192 else
193 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
194
195 // store the larger mac address for backward compatible of
196 // ralink proprietary STA-key issue
197 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
198 CurrPos += 6;
199
200 // Get smaller Nonce
201 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
202 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
203 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
204 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
205 else
206 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
207 CurrPos += 32;
208
209 // Get larger Nonce
210 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
211 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
212 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
213 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
214 else
215 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
216 CurrPos += 32;
217
218 hex_dump("concatenation=", concatenation, 76);
219
220 // Use PRF to generate PTK
221 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
222
223 }
224
225 /*
226 ========================================================================
227
228 Routine Description:
229 Generate random number by software.
230
231 Arguments:
232 pAd - pointer to our pAdapter context
233 macAddr - pointer to local MAC address
234
235 Return Value:
236
237 Note:
238 802.1ii-2004 Annex H.5
239
240 ========================================================================
241 */
242 VOID GenRandom(
243 IN PRTMP_ADAPTER pAd,
244 IN UCHAR *macAddr,
245 OUT UCHAR *random)
246 {
247 INT i, curr;
248 UCHAR local[80], KeyCounter[32];
249 UCHAR result[80];
250 ULONG CurrentTime;
251 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
252
253 // Zero the related information
254 NdisZeroMemory(result, 80);
255 NdisZeroMemory(local, 80);
256 NdisZeroMemory(KeyCounter, 32);
257
258 for (i = 0; i < 32; i++)
259 {
260 // copy the local MAC address
261 COPY_MAC_ADDR(local, macAddr);
262 curr = MAC_ADDR_LEN;
263
264 // concatenate the current time
265 NdisGetSystemUpTime(&CurrentTime);
266 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
267 curr += sizeof(CurrentTime);
268
269 // concatenate the last result
270 NdisMoveMemory(&local[curr], result, 32);
271 curr += 32;
272
273 // concatenate a variable
274 NdisMoveMemory(&local[curr], &i, 2);
275 curr += 2;
276
277 // calculate the result
278 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
279 }
280
281 NdisMoveMemory(random, result, 32);
282 }
283
284 /*
285 ========================================================================
286
287 Routine Description:
288 Build cipher suite in RSN-IE.
289 It only shall be called by RTMPMakeRSNIE.
290
291 Arguments:
292 pAd - pointer to our pAdapter context
293 ElementID - indicate the WPA1 or WPA2
294 WepStatus - indicate the encryption type
295 bMixCipher - a boolean to indicate the pairwise cipher and group
296 cipher are the same or not
297
298 Return Value:
299
300 Note:
301
302 ========================================================================
303 */
304 static VOID RTMPInsertRsnIeCipher(
305 IN PRTMP_ADAPTER pAd,
306 IN UCHAR ElementID,
307 IN UINT WepStatus,
308 IN BOOLEAN bMixCipher,
309 IN UCHAR FlexibleCipher,
310 OUT PUCHAR pRsnIe,
311 OUT UCHAR *rsn_len)
312 {
313 UCHAR PairwiseCnt;
314
315 *rsn_len = 0;
316
317 // decide WPA2 or WPA1
318 if (ElementID == Wpa2Ie)
319 {
320 RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
321
322 // Assign the verson as 1
323 pRsnie_cipher->version = 1;
324
325 switch (WepStatus)
326 {
327 // TKIP mode
328 case Ndis802_11Encryption2Enabled:
329 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
330 pRsnie_cipher->ucount = 1;
331 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
332 *rsn_len = sizeof(RSNIE2);
333 break;
334
335 // AES mode
336 case Ndis802_11Encryption3Enabled:
337 if (bMixCipher)
338 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
339 else
340 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
341 pRsnie_cipher->ucount = 1;
342 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
343 *rsn_len = sizeof(RSNIE2);
344 break;
345
346 // TKIP-AES mix mode
347 case Ndis802_11Encryption4Enabled:
348 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
349
350 PairwiseCnt = 1;
351 // Insert WPA2 TKIP as the first pairwise cipher
352 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
353 {
354 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
355 // Insert WPA2 AES as the secondary pairwise cipher
356 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
357 {
358 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
359 PairwiseCnt = 2;
360 }
361 }
362 else
363 {
364 // Insert WPA2 AES as the first pairwise cipher
365 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
366 }
367
368 pRsnie_cipher->ucount = PairwiseCnt;
369 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
370 break;
371 }
372
373 if ((pAd->OpMode == OPMODE_STA) &&
374 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
375 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
376 {
377 UINT GroupCipher = pAd->StaCfg.GroupCipher;
378 switch(GroupCipher)
379 {
380 case Ndis802_11GroupWEP40Enabled:
381 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
382 break;
383 case Ndis802_11GroupWEP104Enabled:
384 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
385 break;
386 }
387 }
388
389 // swap for big-endian platform
390 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
391 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
392 }
393 else
394 {
395 RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
396
397 // Assign OUI and version
398 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
399 pRsnie_cipher->version = 1;
400
401 switch (WepStatus)
402 {
403 // TKIP mode
404 case Ndis802_11Encryption2Enabled:
405 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
406 pRsnie_cipher->ucount = 1;
407 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
408 *rsn_len = sizeof(RSNIE);
409 break;
410
411 // AES mode
412 case Ndis802_11Encryption3Enabled:
413 if (bMixCipher)
414 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
415 else
416 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
417 pRsnie_cipher->ucount = 1;
418 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
419 *rsn_len = sizeof(RSNIE);
420 break;
421
422 // TKIP-AES mix mode
423 case Ndis802_11Encryption4Enabled:
424 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
425
426 PairwiseCnt = 1;
427 // Insert WPA TKIP as the first pairwise cipher
428 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
429 {
430 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
431 // Insert WPA AES as the secondary pairwise cipher
432 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
433 {
434 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
435 PairwiseCnt = 2;
436 }
437 }
438 else
439 {
440 // Insert WPA AES as the first pairwise cipher
441 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
442 }
443
444 pRsnie_cipher->ucount = PairwiseCnt;
445 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
446 break;
447 }
448
449 if ((pAd->OpMode == OPMODE_STA) &&
450 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
451 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
452 {
453 UINT GroupCipher = pAd->StaCfg.GroupCipher;
454 switch(GroupCipher)
455 {
456 case Ndis802_11GroupWEP40Enabled:
457 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
458 break;
459 case Ndis802_11GroupWEP104Enabled:
460 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
461 break;
462 }
463 }
464
465 // swap for big-endian platform
466 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
467 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
468 }
469 }
470
471 /*
472 ========================================================================
473
474 Routine Description:
475 Build AKM suite in RSN-IE.
476 It only shall be called by RTMPMakeRSNIE.
477
478 Arguments:
479 pAd - pointer to our pAdapter context
480 ElementID - indicate the WPA1 or WPA2
481 AuthMode - indicate the authentication mode
482 apidx - indicate the interface index
483
484 Return Value:
485
486 Note:
487
488 ========================================================================
489 */
490 static VOID RTMPInsertRsnIeAKM(
491 IN PRTMP_ADAPTER pAd,
492 IN UCHAR ElementID,
493 IN UINT AuthMode,
494 IN UCHAR apidx,
495 OUT PUCHAR pRsnIe,
496 OUT UCHAR *rsn_len)
497 {
498 RSNIE_AUTH *pRsnie_auth;
499
500 pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
501
502 // decide WPA2 or WPA1
503 if (ElementID == Wpa2Ie)
504 {
505 switch (AuthMode)
506 {
507 case Ndis802_11AuthModeWPA2:
508 case Ndis802_11AuthModeWPA1WPA2:
509 pRsnie_auth->acount = 1;
510 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
511 break;
512
513 case Ndis802_11AuthModeWPA2PSK:
514 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
515 pRsnie_auth->acount = 1;
516 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
517 break;
518 }
519 }
520 else
521 {
522 switch (AuthMode)
523 {
524 case Ndis802_11AuthModeWPA:
525 case Ndis802_11AuthModeWPA1WPA2:
526 pRsnie_auth->acount = 1;
527 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
528 break;
529
530 case Ndis802_11AuthModeWPAPSK:
531 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
532 pRsnie_auth->acount = 1;
533 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
534 break;
535
536 case Ndis802_11AuthModeWPANone:
537 pRsnie_auth->acount = 1;
538 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
539 break;
540 }
541 }
542
543 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
544
545 (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length
546
547 }
548
549 /*
550 ========================================================================
551
552 Routine Description:
553 Build capability in RSN-IE.
554 It only shall be called by RTMPMakeRSNIE.
555
556 Arguments:
557 pAd - pointer to our pAdapter context
558 ElementID - indicate the WPA1 or WPA2
559 apidx - indicate the interface index
560
561 Return Value:
562
563 Note:
564
565 ========================================================================
566 */
567 static VOID RTMPInsertRsnIeCap(
568 IN PRTMP_ADAPTER pAd,
569 IN UCHAR ElementID,
570 IN UCHAR apidx,
571 OUT PUCHAR pRsnIe,
572 OUT UCHAR *rsn_len)
573 {
574 RSN_CAPABILITIES *pRSN_Cap;
575
576 // it could be ignored in WPA1 mode
577 if (ElementID == WpaIe)
578 return;
579
580 pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
581
582
583 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
584
585 (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
586
587 }
588
589
590 /*
591 ========================================================================
592
593 Routine Description:
594 Build RSN IE context. It is not included element-ID and length.
595
596 Arguments:
597 pAd - pointer to our pAdapter context
598 AuthMode - indicate the authentication mode
599 WepStatus - indicate the encryption type
600 apidx - indicate the interface index
601
602 Return Value:
603
604 Note:
605
606 ========================================================================
607 */
608 VOID RTMPMakeRSNIE(
609 IN PRTMP_ADAPTER pAd,
610 IN UINT AuthMode,
611 IN UINT WepStatus,
612 IN UCHAR apidx)
613 {
614 PUCHAR pRsnIe = NULL; // primary RSNIE
615 UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE
616 UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
617 UCHAR PrimaryRsnie;
618 BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
619 UCHAR p_offset;
620 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
621
622 rsnielen_cur_p = NULL;
623 rsnielen_ex_cur_p = NULL;
624
625 {
626 {
627 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
628 {
629 if (AuthMode < Ndis802_11AuthModeWPA)
630 return;
631 }
632 else
633 {
634 // Support WPAPSK or WPA2PSK in STA-Infra mode
635 // Support WPANone in STA-Adhoc mode
636 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
637 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
638 (AuthMode != Ndis802_11AuthModeWPANone)
639 )
640 return;
641 }
642
643 DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
644
645 // Zero RSNIE context
646 pAd->StaCfg.RSNIE_Len = 0;
647 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
648
649 // Pointer to RSNIE
650 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
651 pRsnIe = pAd->StaCfg.RSN_IE;
652
653 bMixCipher = pAd->StaCfg.bMixCipher;
654 }
655 }
656
657 // indicate primary RSNIE as WPA or WPA2
658 if ((AuthMode == Ndis802_11AuthModeWPA) ||
659 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
660 (AuthMode == Ndis802_11AuthModeWPANone) ||
661 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
662 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
663 PrimaryRsnie = WpaIe;
664 else
665 PrimaryRsnie = Wpa2Ie;
666
667 {
668 // Build the primary RSNIE
669 // 1. insert cipher suite
670 RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
671
672 // 2. insert AKM
673 RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
674
675 // 3. insert capability
676 RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
677 }
678
679 // 4. update the RSNIE length
680 *rsnielen_cur_p = p_offset;
681
682 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
683
684
685 }
686
687 /*
688 ==========================================================================
689 Description:
690 Check whether the received frame is EAP frame.
691
692 Arguments:
693 pAd - pointer to our pAdapter context
694 pEntry - pointer to active entry
695 pData - the received frame
696 DataByteCount - the received frame's length
697 FromWhichBSSID - indicate the interface index
698
699 Return:
700 TRUE - This frame is EAP frame
701 FALSE - otherwise
702 ==========================================================================
703 */
704 BOOLEAN RTMPCheckWPAframe(
705 IN PRTMP_ADAPTER pAd,
706 IN PMAC_TABLE_ENTRY pEntry,
707 IN PUCHAR pData,
708 IN ULONG DataByteCount,
709 IN UCHAR FromWhichBSSID)
710 {
711 ULONG Body_len;
712 BOOLEAN Cancelled;
713
714
715 if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
716 return FALSE;
717
718
719 // Skip LLC header
720 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
721 // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
722 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
723 {
724 pData += 6;
725 }
726 // Skip 2-bytes EAPoL type
727 if (NdisEqualMemory(EAPOL, pData, 2))
728 {
729 pData += 2;
730 }
731 else
732 return FALSE;
733
734 switch (*(pData+1))
735 {
736 case EAPPacket:
737 Body_len = (*(pData+2)<<8) | (*(pData+3));
738 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
739 break;
740 case EAPOLStart:
741 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
742 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
743 {
744 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
745 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
746 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
747 }
748 break;
749 case EAPOLLogoff:
750 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
751 break;
752 case EAPOLKey:
753 Body_len = (*(pData+2)<<8) | (*(pData+3));
754 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
755 break;
756 case EAPOLASFAlert:
757 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
758 break;
759 default:
760 return FALSE;
761
762 }
763 return TRUE;
764 }
765
766 /*
767 ========================================================================
768
769 Routine Description:
770 Misc function to decrypt AES body
771
772 Arguments:
773
774 Return Value:
775
776 Note:
777 This function references to RFC 3394 for aes key unwrap algorithm.
778
779 ========================================================================
780 */
781 VOID AES_GTK_KEY_UNWRAP(
782 IN UCHAR *key,
783 OUT UCHAR *plaintext,
784 IN UCHAR c_len,
785 IN UCHAR *ciphertext)
786
787 {
788 UCHAR A[8], BIN[16], BOUT[16];
789 UCHAR xor;
790 INT i, j;
791 aes_context aesctx;
792 UCHAR *R;
793 INT num_blocks = c_len/8; // unit:64bits
794
795
796 os_alloc_mem(NULL, (PUCHAR *)&R, 512);
797
798 if (R == NULL)
799 {
800 DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
801 return;
802 } /* End of if */
803
804 // Initialize
805 NdisMoveMemory(A, ciphertext, 8);
806 //Input plaintext
807 for(i = 0; i < (c_len-8); i++)
808 {
809 R[ i] = ciphertext[i + 8];
810 }
811
812 rtmp_aes_set_key(&aesctx, key, 128);
813
814 for(j = 5; j >= 0; j--)
815 {
816 for(i = (num_blocks-1); i > 0; i--)
817 {
818 xor = (num_blocks -1 )* j + i;
819 NdisMoveMemory(BIN, A, 8);
820 BIN[7] = A[7] ^ xor;
821 NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
822 rtmp_aes_decrypt(&aesctx, BIN, BOUT);
823 NdisMoveMemory(A, &BOUT[0], 8);
824 NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
825 }
826 }
827
828 // OUTPUT
829 for(i = 0; i < c_len; i++)
830 {
831 plaintext[i] = R[i];
832 }
833
834
835 os_free_mem(NULL, R);
836 }
This page took 0.078911 seconds and 6 git commands to generate.