Merge branch 'upstream/wm8974' into for-2.6.33
[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 #ifndef RT30xx
43 UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01};
44 #endif
45 UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
46 UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
47 #ifndef RT30xx
48 UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05};
49 #endif
50 UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
51 UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
52 // WPA2 OUI
53 UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
54 UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
55 UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
56 UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
57 UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
58 #ifndef RT30xx
59 UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05};
60 #endif
61 // MSA OUI
62 UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06
63 UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06
64
65 /*
66 ========================================================================
67
68 Routine Description:
69 The pseudo-random function(PRF) that hashes various inputs to
70 derive a pseudo-random value. To add liveness to the pseudo-random
71 value, a nonce should be one of the inputs.
72
73 It is used to generate PTK, GTK or some specific random value.
74
75 Arguments:
76 UCHAR *key, - the key material for HMAC_SHA1 use
77 INT key_len - the length of key
78 UCHAR *prefix - a prefix label
79 INT prefix_len - the length of the label
80 UCHAR *data - a specific data with variable length
81 INT data_len - the length of a specific data
82 INT len - the output lenght
83
84 Return Value:
85 UCHAR *output - the calculated result
86
87 Note:
88 802.11i-2004 Annex H.3
89
90 ========================================================================
91 */
92 VOID PRF(
93 IN UCHAR *key,
94 IN INT key_len,
95 IN UCHAR *prefix,
96 IN INT prefix_len,
97 IN UCHAR *data,
98 IN INT data_len,
99 OUT UCHAR *output,
100 IN INT len)
101 {
102 INT i;
103 UCHAR *input;
104 INT currentindex = 0;
105 INT total_len;
106
107 // Allocate memory for input
108 os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
109
110 if (input == NULL)
111 {
112 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
113 return;
114 }
115
116 // Generate concatenation input
117 NdisMoveMemory(input, prefix, prefix_len);
118
119 // Concatenate a single octet containing 0
120 input[prefix_len] = 0;
121
122 // Concatenate specific data
123 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
124 total_len = prefix_len + 1 + data_len;
125
126 // Concatenate a single octet containing 0
127 // This octet shall be update later
128 input[total_len] = 0;
129 total_len++;
130
131 // Iterate to calculate the result by hmac-sha-1
132 // Then concatenate to last result
133 for (i = 0; i < (len + 19) / 20; i++)
134 {
135 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
136 currentindex += 20;
137
138 // update the last octet
139 input[total_len - 1]++;
140 }
141 os_free_mem(NULL, input);
142 }
143
144 /*
145 ========================================================================
146
147 Routine Description:
148 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
149 It shall be called by 4-way handshake processing.
150
151 Arguments:
152 pAd - pointer to our pAdapter context
153 PMK - pointer to PMK
154 ANonce - pointer to ANonce
155 AA - pointer to Authenticator Address
156 SNonce - pointer to SNonce
157 SA - pointer to Supplicant Address
158 len - indicate the length of PTK (octet)
159
160 Return Value:
161 Output pointer to the PTK
162
163 Note:
164 Refer to IEEE 802.11i-2004 8.5.1.2
165
166 ========================================================================
167 */
168 VOID WpaCountPTK(
169 IN PRTMP_ADAPTER pAd,
170 IN UCHAR *PMK,
171 IN UCHAR *ANonce,
172 IN UCHAR *AA,
173 IN UCHAR *SNonce,
174 IN UCHAR *SA,
175 OUT UCHAR *output,
176 IN UINT len)
177 {
178 UCHAR concatenation[76];
179 UINT CurrPos = 0;
180 UCHAR temp[32];
181 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
182 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
183
184 // initiate the concatenation input
185 NdisZeroMemory(temp, sizeof(temp));
186 NdisZeroMemory(concatenation, 76);
187
188 // Get smaller address
189 if (RTMPCompareMemory(SA, AA, 6) == 1)
190 NdisMoveMemory(concatenation, AA, 6);
191 else
192 NdisMoveMemory(concatenation, SA, 6);
193 CurrPos += 6;
194
195 // Get larger address
196 if (RTMPCompareMemory(SA, AA, 6) == 1)
197 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
198 else
199 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
200
201 // store the larger mac address for backward compatible of
202 // ralink proprietary STA-key issue
203 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
204 CurrPos += 6;
205
206 // Get smaller Nonce
207 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
208 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
209 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
210 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
211 else
212 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
213 CurrPos += 32;
214
215 // Get larger Nonce
216 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
217 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
218 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
219 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
220 else
221 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
222 CurrPos += 32;
223
224 hex_dump("concatenation=", concatenation, 76);
225
226 // Use PRF to generate PTK
227 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
228
229 }
230
231 /*
232 ========================================================================
233
234 Routine Description:
235 Generate random number by software.
236
237 Arguments:
238 pAd - pointer to our pAdapter context
239 macAddr - pointer to local MAC address
240
241 Return Value:
242
243 Note:
244 802.1ii-2004 Annex H.5
245
246 ========================================================================
247 */
248 VOID GenRandom(
249 IN PRTMP_ADAPTER pAd,
250 IN UCHAR *macAddr,
251 OUT UCHAR *random)
252 {
253 INT i, curr;
254 UCHAR local[80], KeyCounter[32];
255 UCHAR result[80];
256 ULONG CurrentTime;
257 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
258
259 // Zero the related information
260 NdisZeroMemory(result, 80);
261 NdisZeroMemory(local, 80);
262 NdisZeroMemory(KeyCounter, 32);
263
264 for (i = 0; i < 32; i++)
265 {
266 // copy the local MAC address
267 COPY_MAC_ADDR(local, macAddr);
268 curr = MAC_ADDR_LEN;
269
270 // concatenate the current time
271 NdisGetSystemUpTime(&CurrentTime);
272 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
273 curr += sizeof(CurrentTime);
274
275 // concatenate the last result
276 NdisMoveMemory(&local[curr], result, 32);
277 curr += 32;
278
279 // concatenate a variable
280 NdisMoveMemory(&local[curr], &i, 2);
281 curr += 2;
282
283 // calculate the result
284 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
285 }
286
287 NdisMoveMemory(random, result, 32);
288 }
289
290 /*
291 ========================================================================
292
293 Routine Description:
294 Build cipher suite in RSN-IE.
295 It only shall be called by RTMPMakeRSNIE.
296
297 Arguments:
298 pAd - pointer to our pAdapter context
299 ElementID - indicate the WPA1 or WPA2
300 WepStatus - indicate the encryption type
301 bMixCipher - a boolean to indicate the pairwise cipher and group
302 cipher are the same or not
303
304 Return Value:
305
306 Note:
307
308 ========================================================================
309 */
310 static VOID RTMPInsertRsnIeCipher(
311 IN PRTMP_ADAPTER pAd,
312 IN UCHAR ElementID,
313 IN UINT WepStatus,
314 IN BOOLEAN bMixCipher,
315 IN UCHAR FlexibleCipher,
316 OUT PUCHAR pRsnIe,
317 OUT UCHAR *rsn_len)
318 {
319 UCHAR PairwiseCnt;
320
321 *rsn_len = 0;
322
323 // decide WPA2 or WPA1
324 if (ElementID == Wpa2Ie)
325 {
326 RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
327
328 // Assign the verson as 1
329 pRsnie_cipher->version = 1;
330
331 switch (WepStatus)
332 {
333 // TKIP mode
334 case Ndis802_11Encryption2Enabled:
335 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
336 pRsnie_cipher->ucount = 1;
337 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
338 *rsn_len = sizeof(RSNIE2);
339 break;
340
341 // AES mode
342 case Ndis802_11Encryption3Enabled:
343 if (bMixCipher)
344 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
345 else
346 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
347 pRsnie_cipher->ucount = 1;
348 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
349 *rsn_len = sizeof(RSNIE2);
350 break;
351
352 // TKIP-AES mix mode
353 case Ndis802_11Encryption4Enabled:
354 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
355
356 PairwiseCnt = 1;
357 // Insert WPA2 TKIP as the first pairwise cipher
358 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
359 {
360 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
361 // Insert WPA2 AES as the secondary pairwise cipher
362 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
363 {
364 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
365 PairwiseCnt = 2;
366 }
367 }
368 else
369 {
370 // Insert WPA2 AES as the first pairwise cipher
371 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
372 }
373
374 pRsnie_cipher->ucount = PairwiseCnt;
375 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
376 break;
377 }
378
379 #ifndef RT30xx
380 if ((pAd->OpMode == OPMODE_STA) &&
381 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
382 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
383 {
384 UINT GroupCipher = pAd->StaCfg.GroupCipher;
385 switch(GroupCipher)
386 {
387 case Ndis802_11GroupWEP40Enabled:
388 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
389 break;
390 case Ndis802_11GroupWEP104Enabled:
391 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
392 break;
393 }
394 }
395 #endif
396 // swap for big-endian platform
397 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
398 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
399 }
400 else
401 {
402 RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
403
404 // Assign OUI and version
405 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
406 pRsnie_cipher->version = 1;
407
408 switch (WepStatus)
409 {
410 // TKIP mode
411 case Ndis802_11Encryption2Enabled:
412 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
413 pRsnie_cipher->ucount = 1;
414 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
415 *rsn_len = sizeof(RSNIE);
416 break;
417
418 // AES mode
419 case Ndis802_11Encryption3Enabled:
420 if (bMixCipher)
421 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
422 else
423 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
424 pRsnie_cipher->ucount = 1;
425 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
426 *rsn_len = sizeof(RSNIE);
427 break;
428
429 // TKIP-AES mix mode
430 case Ndis802_11Encryption4Enabled:
431 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
432
433 PairwiseCnt = 1;
434 // Insert WPA TKIP as the first pairwise cipher
435 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
436 {
437 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
438 // Insert WPA AES as the secondary pairwise cipher
439 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
440 {
441 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
442 PairwiseCnt = 2;
443 }
444 }
445 else
446 {
447 // Insert WPA AES as the first pairwise cipher
448 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
449 }
450
451 pRsnie_cipher->ucount = PairwiseCnt;
452 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
453 break;
454 }
455
456 #ifndef RT30xx
457 if ((pAd->OpMode == OPMODE_STA) &&
458 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
459 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
460 {
461 UINT GroupCipher = pAd->StaCfg.GroupCipher;
462 switch(GroupCipher)
463 {
464 case Ndis802_11GroupWEP40Enabled:
465 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
466 break;
467 case Ndis802_11GroupWEP104Enabled:
468 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
469 break;
470 }
471 }
472 #endif
473 // swap for big-endian platform
474 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
475 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
476 }
477 }
478
479 /*
480 ========================================================================
481
482 Routine Description:
483 Build AKM suite in RSN-IE.
484 It only shall be called by RTMPMakeRSNIE.
485
486 Arguments:
487 pAd - pointer to our pAdapter context
488 ElementID - indicate the WPA1 or WPA2
489 AuthMode - indicate the authentication mode
490 apidx - indicate the interface index
491
492 Return Value:
493
494 Note:
495
496 ========================================================================
497 */
498 static VOID RTMPInsertRsnIeAKM(
499 IN PRTMP_ADAPTER pAd,
500 IN UCHAR ElementID,
501 IN UINT AuthMode,
502 IN UCHAR apidx,
503 OUT PUCHAR pRsnIe,
504 OUT UCHAR *rsn_len)
505 {
506 RSNIE_AUTH *pRsnie_auth;
507
508 pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
509
510 // decide WPA2 or WPA1
511 if (ElementID == Wpa2Ie)
512 {
513 switch (AuthMode)
514 {
515 case Ndis802_11AuthModeWPA2:
516 case Ndis802_11AuthModeWPA1WPA2:
517 pRsnie_auth->acount = 1;
518 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
519 break;
520
521 case Ndis802_11AuthModeWPA2PSK:
522 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
523 pRsnie_auth->acount = 1;
524 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
525 break;
526 }
527 }
528 else
529 {
530 switch (AuthMode)
531 {
532 case Ndis802_11AuthModeWPA:
533 case Ndis802_11AuthModeWPA1WPA2:
534 pRsnie_auth->acount = 1;
535 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
536 break;
537
538 case Ndis802_11AuthModeWPAPSK:
539 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
540 pRsnie_auth->acount = 1;
541 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
542 break;
543
544 case Ndis802_11AuthModeWPANone:
545 pRsnie_auth->acount = 1;
546 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
547 break;
548 }
549 }
550
551 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
552
553 (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length
554
555 }
556
557 /*
558 ========================================================================
559
560 Routine Description:
561 Build capability in RSN-IE.
562 It only shall be called by RTMPMakeRSNIE.
563
564 Arguments:
565 pAd - pointer to our pAdapter context
566 ElementID - indicate the WPA1 or WPA2
567 apidx - indicate the interface index
568
569 Return Value:
570
571 Note:
572
573 ========================================================================
574 */
575 static VOID RTMPInsertRsnIeCap(
576 IN PRTMP_ADAPTER pAd,
577 IN UCHAR ElementID,
578 IN UCHAR apidx,
579 OUT PUCHAR pRsnIe,
580 OUT UCHAR *rsn_len)
581 {
582 RSN_CAPABILITIES *pRSN_Cap;
583
584 // it could be ignored in WPA1 mode
585 if (ElementID == WpaIe)
586 return;
587
588 pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
589
590
591 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
592
593 (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
594
595 }
596
597
598 /*
599 ========================================================================
600
601 Routine Description:
602 Build RSN IE context. It is not included element-ID and length.
603
604 Arguments:
605 pAd - pointer to our pAdapter context
606 AuthMode - indicate the authentication mode
607 WepStatus - indicate the encryption type
608 apidx - indicate the interface index
609
610 Return Value:
611
612 Note:
613
614 ========================================================================
615 */
616 VOID RTMPMakeRSNIE(
617 IN PRTMP_ADAPTER pAd,
618 IN UINT AuthMode,
619 IN UINT WepStatus,
620 IN UCHAR apidx)
621 {
622 PUCHAR pRsnIe = NULL; // primary RSNIE
623 UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE
624 UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
625 UCHAR PrimaryRsnie;
626 BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
627 UCHAR p_offset;
628 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
629
630 rsnielen_cur_p = NULL;
631 rsnielen_ex_cur_p = NULL;
632
633 {
634 {
635 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
636 {
637 if (AuthMode < Ndis802_11AuthModeWPA)
638 return;
639 }
640 else
641 {
642 // Support WPAPSK or WPA2PSK in STA-Infra mode
643 // Support WPANone in STA-Adhoc mode
644 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
645 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
646 (AuthMode != Ndis802_11AuthModeWPANone)
647 )
648 return;
649 }
650
651 DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
652
653 // Zero RSNIE context
654 pAd->StaCfg.RSNIE_Len = 0;
655 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
656
657 // Pointer to RSNIE
658 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
659 pRsnIe = pAd->StaCfg.RSN_IE;
660
661 bMixCipher = pAd->StaCfg.bMixCipher;
662 }
663 }
664
665 // indicate primary RSNIE as WPA or WPA2
666 if ((AuthMode == Ndis802_11AuthModeWPA) ||
667 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
668 (AuthMode == Ndis802_11AuthModeWPANone) ||
669 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
670 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
671 PrimaryRsnie = WpaIe;
672 else
673 PrimaryRsnie = Wpa2Ie;
674
675 {
676 // Build the primary RSNIE
677 // 1. insert cipher suite
678 RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
679
680 // 2. insert AKM
681 RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
682
683 // 3. insert capability
684 RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
685 }
686
687 // 4. update the RSNIE length
688 *rsnielen_cur_p = p_offset;
689
690 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
691
692
693 }
694
695 /*
696 ==========================================================================
697 Description:
698 Check whether the received frame is EAP frame.
699
700 Arguments:
701 pAd - pointer to our pAdapter context
702 pEntry - pointer to active entry
703 pData - the received frame
704 DataByteCount - the received frame's length
705 FromWhichBSSID - indicate the interface index
706
707 Return:
708 TRUE - This frame is EAP frame
709 FALSE - otherwise
710 ==========================================================================
711 */
712 BOOLEAN RTMPCheckWPAframe(
713 IN PRTMP_ADAPTER pAd,
714 IN PMAC_TABLE_ENTRY pEntry,
715 IN PUCHAR pData,
716 IN ULONG DataByteCount,
717 IN UCHAR FromWhichBSSID)
718 {
719 ULONG Body_len;
720 BOOLEAN Cancelled;
721
722
723 if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
724 return FALSE;
725
726
727 // Skip LLC header
728 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
729 // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
730 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
731 {
732 pData += 6;
733 }
734 // Skip 2-bytes EAPoL type
735 if (NdisEqualMemory(EAPOL, pData, 2))
736 {
737 pData += 2;
738 }
739 else
740 return FALSE;
741
742 switch (*(pData+1))
743 {
744 case EAPPacket:
745 Body_len = (*(pData+2)<<8) | (*(pData+3));
746 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
747 break;
748 case EAPOLStart:
749 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
750 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
751 {
752 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
753 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
754 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
755 }
756 break;
757 case EAPOLLogoff:
758 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
759 break;
760 case EAPOLKey:
761 Body_len = (*(pData+2)<<8) | (*(pData+3));
762 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
763 break;
764 case EAPOLASFAlert:
765 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
766 break;
767 default:
768 return FALSE;
769
770 }
771 return TRUE;
772 }
773
774
775 /*
776 ==========================================================================
777 Description:
778 ENCRYPT AES GTK before sending in EAPOL frame.
779 AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function.
780 This function references to RFC 3394 for aes key wrap algorithm.
781 Return:
782 ==========================================================================
783 */
784 VOID AES_GTK_KEY_WRAP(
785 IN UCHAR *key,
786 IN UCHAR *plaintext,
787 IN UCHAR p_len,
788 OUT UCHAR *ciphertext)
789 {
790 UCHAR A[8], BIN[16], BOUT[16];
791 UCHAR R[512];
792 INT num_blocks = p_len/8; // unit:64bits
793 INT i, j;
794 aes_context aesctx;
795 UCHAR xor;
796
797 rtmp_aes_set_key(&aesctx, key, 128);
798
799 // Init IA
800 for (i = 0; i < 8; i++)
801 A[i] = 0xa6;
802
803 //Input plaintext
804 for (i = 0; i < num_blocks; i++)
805 {
806 for (j = 0 ; j < 8; j++)
807 R[8 * (i + 1) + j] = plaintext[8 * i + j];
808 }
809
810 // Key Mix
811 for (j = 0; j < 6; j++)
812 {
813 for(i = 1; i <= num_blocks; i++)
814 {
815 //phase 1
816 NdisMoveMemory(BIN, A, 8);
817 NdisMoveMemory(&BIN[8], &R[8 * i], 8);
818 rtmp_aes_encrypt(&aesctx, BIN, BOUT);
819
820 NdisMoveMemory(A, &BOUT[0], 8);
821 xor = num_blocks * j + i;
822 A[7] = BOUT[7] ^ xor;
823 NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
824 }
825 }
826
827 // Output ciphertext
828 NdisMoveMemory(ciphertext, A, 8);
829
830 for (i = 1; i <= num_blocks; i++)
831 {
832 for (j = 0 ; j < 8; j++)
833 ciphertext[8 * i + j] = R[8 * i + j];
834 }
835 }
836
837
838 /*
839 ========================================================================
840
841 Routine Description:
842 Misc function to decrypt AES body
843
844 Arguments:
845
846 Return Value:
847
848 Note:
849 This function references to RFC 3394 for aes key unwrap algorithm.
850
851 ========================================================================
852 */
853 VOID AES_GTK_KEY_UNWRAP(
854 IN UCHAR *key,
855 OUT UCHAR *plaintext,
856 IN UCHAR c_len,
857 IN UCHAR *ciphertext)
858
859 {
860 UCHAR A[8], BIN[16], BOUT[16];
861 UCHAR xor;
862 INT i, j;
863 aes_context aesctx;
864 UCHAR *R;
865 INT num_blocks = c_len/8; // unit:64bits
866
867
868 os_alloc_mem(NULL, (PUCHAR *)&R, 512);
869
870 if (R == NULL)
871 {
872 DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
873 return;
874 } /* End of if */
875
876 // Initialize
877 NdisMoveMemory(A, ciphertext, 8);
878 //Input plaintext
879 for(i = 0; i < (c_len-8); i++)
880 {
881 R[ i] = ciphertext[i + 8];
882 }
883
884 rtmp_aes_set_key(&aesctx, key, 128);
885
886 for(j = 5; j >= 0; j--)
887 {
888 for(i = (num_blocks-1); i > 0; i--)
889 {
890 xor = (num_blocks -1 )* j + i;
891 NdisMoveMemory(BIN, A, 8);
892 BIN[7] = A[7] ^ xor;
893 NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
894 rtmp_aes_decrypt(&aesctx, BIN, BOUT);
895 NdisMoveMemory(A, &BOUT[0], 8);
896 NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
897 }
898 }
899
900 // OUTPUT
901 for(i = 0; i < c_len; i++)
902 {
903 plaintext[i] = R[i];
904 }
905
906
907 os_free_mem(NULL, R);
908 }
909
910 /*
911 ==========================================================================
912 Description:
913 Report the EAP message type
914
915 Arguments:
916 msg - EAPOL_PAIR_MSG_1
917 EAPOL_PAIR_MSG_2
918 EAPOL_PAIR_MSG_3
919 EAPOL_PAIR_MSG_4
920 EAPOL_GROUP_MSG_1
921 EAPOL_GROUP_MSG_2
922
923 Return:
924 message type string
925
926 ==========================================================================
927 */
928 CHAR *GetEapolMsgType(CHAR msg)
929 {
930 if(msg == EAPOL_PAIR_MSG_1)
931 return "Pairwise Message 1";
932 else if(msg == EAPOL_PAIR_MSG_2)
933 return "Pairwise Message 2";
934 else if(msg == EAPOL_PAIR_MSG_3)
935 return "Pairwise Message 3";
936 else if(msg == EAPOL_PAIR_MSG_4)
937 return "Pairwise Message 4";
938 else if(msg == EAPOL_GROUP_MSG_1)
939 return "Group Message 1";
940 else if(msg == EAPOL_GROUP_MSG_2)
941 return "Group Message 2";
942 else
943 return "Invalid Message";
944 }
945
946
947 /*
948 ========================================================================
949
950 Routine Description:
951 Check Sanity RSN IE of EAPoL message
952
953 Arguments:
954
955 Return Value:
956
957
958 ========================================================================
959 */
960 BOOLEAN RTMPCheckRSNIE(
961 IN PRTMP_ADAPTER pAd,
962 IN PUCHAR pData,
963 IN UCHAR DataLen,
964 IN MAC_TABLE_ENTRY *pEntry,
965 OUT UCHAR *Offset)
966 {
967 PUCHAR pVIE;
968 UCHAR len;
969 PEID_STRUCT pEid;
970 BOOLEAN result = FALSE;
971
972 pVIE = pData;
973 len = DataLen;
974 *Offset = 0;
975
976 while (len > sizeof(RSNIE2))
977 {
978 pEid = (PEID_STRUCT) pVIE;
979 // WPA RSN IE
980 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
981 {
982 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
983 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
984 (pEntry->RSNIE_Len == (pEid->Len + 2)))
985 {
986 result = TRUE;
987 }
988
989 *Offset += (pEid->Len + 2);
990 }
991 // WPA2 RSN IE
992 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
993 {
994 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
995 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
996 (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
997 {
998 result = TRUE;
999 }
1000
1001 *Offset += (pEid->Len + 2);
1002 }
1003 else
1004 {
1005 break;
1006 }
1007
1008 pVIE += (pEid->Len + 2);
1009 len -= (pEid->Len + 2);
1010 }
1011
1012
1013 return result;
1014
1015 }
1016
1017
1018 /*
1019 ========================================================================
1020
1021 Routine Description:
1022 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
1023 GTK is encaptulated in KDE format at p.83 802.11i D10
1024
1025 Arguments:
1026
1027 Return Value:
1028
1029 Note:
1030 802.11i D10
1031
1032 ========================================================================
1033 */
1034 BOOLEAN RTMPParseEapolKeyData(
1035 IN PRTMP_ADAPTER pAd,
1036 IN PUCHAR pKeyData,
1037 IN UCHAR KeyDataLen,
1038 IN UCHAR GroupKeyIndex,
1039 IN UCHAR MsgType,
1040 IN BOOLEAN bWPA2,
1041 IN MAC_TABLE_ENTRY *pEntry)
1042 {
1043 PKDE_ENCAP pKDE = NULL;
1044 PUCHAR pMyKeyData = pKeyData;
1045 UCHAR KeyDataLength = KeyDataLen;
1046 UCHAR GTKLEN = 0;
1047 UCHAR DefaultIdx = 0;
1048 UCHAR skip_offset;
1049
1050 // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
1051 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
1052 {
1053 // Check RSN IE whether it is WPA2/WPA2PSK
1054 if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
1055 {
1056 // send wireless event - for RSN IE different
1057 if (pAd->CommonCfg.bWirelessEvent)
1058 RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1059
1060 DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
1061 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
1062 hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
1063
1064 return FALSE;
1065 }
1066 else
1067 {
1068 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
1069 {
1070 // skip RSN IE
1071 pMyKeyData += skip_offset;
1072 KeyDataLength -= skip_offset;
1073 DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1074 }
1075 else
1076 return TRUE;
1077 }
1078 }
1079
1080 DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1081
1082 // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
1083 if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
1084 {
1085 if (KeyDataLength >= 8) // KDE format exclude GTK length
1086 {
1087 pKDE = (PKDE_ENCAP) pMyKeyData;
1088
1089
1090 DefaultIdx = pKDE->GTKEncap.Kid;
1091
1092 // Sanity check - KED length
1093 if (KeyDataLength < (pKDE->Len + 2))
1094 {
1095 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1096 return FALSE;
1097 }
1098
1099 // Get GTK length - refer to IEEE 802.11i-2004 p.82
1100 GTKLEN = pKDE->Len -6;
1101 if (GTKLEN < LEN_AES_KEY)
1102 {
1103 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1104 return FALSE;
1105 }
1106
1107 }
1108 else
1109 {
1110 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
1111 return FALSE;
1112 }
1113
1114 DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
1115 // skip it
1116 pMyKeyData += 8;
1117 KeyDataLength -= 8;
1118
1119 }
1120 else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
1121 {
1122 DefaultIdx = GroupKeyIndex;
1123 DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
1124 }
1125
1126 // Sanity check - shared key index must be 1 ~ 3
1127 if (DefaultIdx < 1 || DefaultIdx > 3)
1128 {
1129 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1130 return FALSE;
1131 }
1132
1133 return TRUE;
1134
1135 }
1136
1137
1138 /*
1139 ========================================================================
1140
1141 Routine Description:
1142 Construct EAPoL message for WPA handshaking
1143 Its format is below,
1144
1145 +--------------------+
1146 | Protocol Version | 1 octet
1147 +--------------------+
1148 | Protocol Type | 1 octet
1149 +--------------------+
1150 | Body Length | 2 octets
1151 +--------------------+
1152 | Descriptor Type | 1 octet
1153 +--------------------+
1154 | Key Information | 2 octets
1155 +--------------------+
1156 | Key Length | 1 octet
1157 +--------------------+
1158 | Key Repaly Counter | 8 octets
1159 +--------------------+
1160 | Key Nonce | 32 octets
1161 +--------------------+
1162 | Key IV | 16 octets
1163 +--------------------+
1164 | Key RSC | 8 octets
1165 +--------------------+
1166 | Key ID or Reserved | 8 octets
1167 +--------------------+
1168 | Key MIC | 16 octets
1169 +--------------------+
1170 | Key Data Length | 2 octets
1171 +--------------------+
1172 | Key Data | n octets
1173 +--------------------+
1174
1175
1176 Arguments:
1177 pAd Pointer to our adapter
1178
1179 Return Value:
1180 None
1181
1182 Note:
1183
1184 ========================================================================
1185 */
1186 VOID ConstructEapolMsg(
1187 IN PRTMP_ADAPTER pAd,
1188 IN UCHAR AuthMode,
1189 IN UCHAR WepStatus,
1190 IN UCHAR GroupKeyWepStatus,
1191 IN UCHAR MsgType,
1192 IN UCHAR DefaultKeyIdx,
1193 IN UCHAR *ReplayCounter,
1194 IN UCHAR *KeyNonce,
1195 IN UCHAR *TxRSC,
1196 IN UCHAR *PTK,
1197 IN UCHAR *GTK,
1198 IN UCHAR *RSNIE,
1199 IN UCHAR RSNIE_Len,
1200 OUT PEAPOL_PACKET pMsg)
1201 {
1202 BOOLEAN bWPA2 = FALSE;
1203
1204 // Choose WPA2 or not
1205 if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
1206 bWPA2 = TRUE;
1207
1208 // Init Packet and Fill header
1209 pMsg->ProVer = EAPOL_VER;
1210 pMsg->ProType = EAPOLKey;
1211
1212 // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
1213 pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
1214
1215 // Fill in EAPoL descriptor
1216 if (bWPA2)
1217 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
1218 else
1219 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
1220
1221 // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
1222 // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
1223 pMsg->KeyDesc.KeyInfo.KeyDescVer =
1224 (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1225
1226 // Specify Key Type as Group(0) or Pairwise(1)
1227 if (MsgType >= EAPOL_GROUP_MSG_1)
1228 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
1229 else
1230 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1231
1232 // Specify Key Index, only group_msg1_WPA1
1233 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
1234 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
1235
1236 if (MsgType == EAPOL_PAIR_MSG_3)
1237 pMsg->KeyDesc.KeyInfo.Install = 1;
1238
1239 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
1240 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
1241
1242 if (MsgType != EAPOL_PAIR_MSG_1)
1243 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
1244
1245 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
1246 {
1247 pMsg->KeyDesc.KeyInfo.Secure = 1;
1248 }
1249
1250 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1251 {
1252 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
1253 }
1254
1255 // key Information element has done.
1256 *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
1257
1258 // Fill in Key Length
1259 {
1260 if (MsgType >= EAPOL_GROUP_MSG_1)
1261 {
1262 // the length of group key cipher
1263 pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
1264 }
1265 else
1266 {
1267 // the length of pairwise key cipher
1268 pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
1269 }
1270 }
1271
1272 // Fill in replay counter
1273 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
1274
1275 // Fill Key Nonce field
1276 // ANonce : pairwise_msg1 & pairwise_msg3
1277 // SNonce : pairwise_msg2
1278 // GNonce : group_msg1_wpa1
1279 if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
1280 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
1281
1282 // Fill key IV - WPA2 as 0, WPA1 as random
1283 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
1284 {
1285 // Suggest IV be random number plus some number,
1286 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
1287 pMsg->KeyDesc.KeyIv[15] += 2;
1288 }
1289
1290 // Fill Key RSC field
1291 // It contains the RSC for the GTK being installed.
1292 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
1293 {
1294 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
1295 }
1296
1297 // Clear Key MIC field for MIC calculation later
1298 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1299
1300 ConstructEapolKeyData(pAd,
1301 AuthMode,
1302 WepStatus,
1303 GroupKeyWepStatus,
1304 MsgType,
1305 DefaultKeyIdx,
1306 bWPA2,
1307 PTK,
1308 GTK,
1309 RSNIE,
1310 RSNIE_Len,
1311 pMsg);
1312
1313 // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
1314 if (MsgType != EAPOL_PAIR_MSG_1)
1315 {
1316 CalculateMIC(pAd, WepStatus, PTK, pMsg);
1317 }
1318
1319 DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
1320 DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1]));
1321 DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1]));
1322
1323
1324 }
1325
1326 /*
1327 ========================================================================
1328
1329 Routine Description:
1330 Construct the Key Data field of EAPoL message
1331
1332 Arguments:
1333 pAd Pointer to our adapter
1334 Elem Message body
1335
1336 Return Value:
1337 None
1338
1339 Note:
1340
1341 ========================================================================
1342 */
1343 VOID ConstructEapolKeyData(
1344 IN PRTMP_ADAPTER pAd,
1345 IN UCHAR AuthMode,
1346 IN UCHAR WepStatus,
1347 IN UCHAR GroupKeyWepStatus,
1348 IN UCHAR MsgType,
1349 IN UCHAR DefaultKeyIdx,
1350 IN BOOLEAN bWPA2Capable,
1351 IN UCHAR *PTK,
1352 IN UCHAR *GTK,
1353 IN UCHAR *RSNIE,
1354 IN UCHAR RSNIE_LEN,
1355 OUT PEAPOL_PACKET pMsg)
1356 {
1357 UCHAR *mpool, *Key_Data, *Rc4GTK;
1358 UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
1359 UCHAR data_offset;
1360
1361
1362 if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
1363 return;
1364
1365 // allocate memory pool
1366 os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
1367
1368 if (mpool == NULL)
1369 return;
1370
1371 /* Rc4GTK Len = 512 */
1372 Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
1373 /* Key_Data Len = 512 */
1374 Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
1375
1376 NdisZeroMemory(Key_Data, 512);
1377 pMsg->KeyDesc.KeyDataLen[1] = 0;
1378 data_offset = 0;
1379
1380 // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
1381 if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
1382 {
1383 if (bWPA2Capable)
1384 Key_Data[data_offset + 0] = IE_WPA2;
1385 else
1386 Key_Data[data_offset + 0] = IE_WPA;
1387
1388 Key_Data[data_offset + 1] = RSNIE_LEN;
1389 NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
1390 data_offset += (2 + RSNIE_LEN);
1391 }
1392
1393 // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
1394 if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
1395 {
1396 // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h
1397 Key_Data[data_offset + 0] = 0xDD;
1398
1399 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1400 {
1401 Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
1402 }
1403 else
1404 {
1405 Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
1406 }
1407
1408 Key_Data[data_offset + 2] = 0x00;
1409 Key_Data[data_offset + 3] = 0x0F;
1410 Key_Data[data_offset + 4] = 0xAC;
1411 Key_Data[data_offset + 5] = 0x01;
1412
1413 // GTK KDE format - 802.11i-2004 Figure-43x
1414 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
1415 Key_Data[data_offset + 7] = 0x00; // Reserved Byte
1416
1417 data_offset += 8;
1418 }
1419
1420
1421 // Encapsulate GTK and encrypt the key-data field with KEK.
1422 // Only for pairwise_msg3_WPA2 and group_msg1
1423 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
1424 {
1425 // Fill in GTK
1426 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1427 {
1428 NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
1429 data_offset += LEN_AES_KEY;
1430 }
1431 else
1432 {
1433 NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
1434 data_offset += TKIP_GTK_LENGTH;
1435 }
1436
1437 // Still dont know why, but if not append will occur "GTK not include in MSG3"
1438 // Patch for compatibility between zero config and funk
1439 if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
1440 {
1441 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
1442 {
1443 Key_Data[data_offset + 0] = 0xDD;
1444 Key_Data[data_offset + 1] = 0;
1445 data_offset += 2;
1446 }
1447 else
1448 {
1449 Key_Data[data_offset + 0] = 0xDD;
1450 Key_Data[data_offset + 1] = 0;
1451 Key_Data[data_offset + 2] = 0;
1452 Key_Data[data_offset + 3] = 0;
1453 Key_Data[data_offset + 4] = 0;
1454 Key_Data[data_offset + 5] = 0;
1455 data_offset += 6;
1456 }
1457 }
1458
1459 // Encrypt the data material in key data field
1460 if (WepStatus == Ndis802_11Encryption3Enabled)
1461 {
1462 AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
1463 // AES wrap function will grow 8 bytes in length
1464 data_offset += 8;
1465 }
1466 else
1467 {
1468 // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
1469 // put TxTsc in Key RSC field
1470 pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32.
1471
1472 // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
1473 NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
1474 NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
1475 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV)
1476 pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
1477 WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
1478 }
1479
1480 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
1481 }
1482 else
1483 {
1484 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
1485 }
1486
1487 // set key data length field and total length
1488 pMsg->KeyDesc.KeyDataLen[1] = data_offset;
1489 pMsg->Body_Len[1] += data_offset;
1490
1491 os_free_mem(pAd, mpool);
1492
1493 }
1494
1495 /*
1496 ========================================================================
1497
1498 Routine Description:
1499 Calcaulate MIC. It is used during 4-ways handsharking.
1500
1501 Arguments:
1502 pAd - pointer to our pAdapter context
1503 PeerWepStatus - indicate the encryption type
1504
1505 Return Value:
1506
1507 Note:
1508
1509 ========================================================================
1510 */
1511 VOID CalculateMIC(
1512 IN PRTMP_ADAPTER pAd,
1513 IN UCHAR PeerWepStatus,
1514 IN UCHAR *PTK,
1515 OUT PEAPOL_PACKET pMsg)
1516 {
1517 UCHAR *OutBuffer;
1518 ULONG FrameLen = 0;
1519 UCHAR mic[LEN_KEY_DESC_MIC];
1520 UCHAR digest[80];
1521
1522 // allocate memory for MIC calculation
1523 os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
1524
1525 if (OutBuffer == NULL)
1526 {
1527 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
1528 return;
1529 }
1530
1531 // make a frame for calculating MIC.
1532 MakeOutgoingFrame(OutBuffer, &FrameLen,
1533 pMsg->Body_Len[1] + 4, pMsg,
1534 END_OF_ARGS);
1535
1536 NdisZeroMemory(mic, sizeof(mic));
1537
1538 // Calculate MIC
1539 if (PeerWepStatus == Ndis802_11Encryption3Enabled)
1540 {
1541 HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
1542 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
1543 }
1544 else
1545 {
1546 hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic);
1547 }
1548
1549 // store the calculated MIC
1550 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
1551
1552 os_free_mem(pAd, OutBuffer);
1553 }
1554
1555 /*
1556 ========================================================================
1557
1558 Routine Description:
1559 Some received frames can't decrypt by Asic, so decrypt them by software.
1560
1561 Arguments:
1562 pAd - pointer to our pAdapter context
1563 PeerWepStatus - indicate the encryption type
1564
1565 Return Value:
1566 NDIS_STATUS_SUCCESS - decryption successful
1567 NDIS_STATUS_FAILURE - decryption failure
1568
1569 ========================================================================
1570 */
1571 NDIS_STATUS RTMPSoftDecryptBroadCastData(
1572 IN PRTMP_ADAPTER pAd,
1573 IN RX_BLK *pRxBlk,
1574 IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
1575 IN PCIPHER_KEY pShard_key)
1576 {
1577 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
1578
1579
1580
1581 // handle WEP decryption
1582 if (GroupCipher == Ndis802_11Encryption1Enabled)
1583 {
1584 if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
1585 {
1586
1587 //Minus IV[4] & ICV[4]
1588 pRxWI->MPDUtotalByteCount -= 8;
1589 }
1590 else
1591 {
1592 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
1593 // give up this frame
1594 return NDIS_STATUS_FAILURE;
1595 }
1596 }
1597 // handle TKIP decryption
1598 else if (GroupCipher == Ndis802_11Encryption2Enabled)
1599 {
1600 if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
1601 {
1602
1603 //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
1604 pRxWI->MPDUtotalByteCount -= 20;
1605 }
1606 else
1607 {
1608 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
1609 // give up this frame
1610 return NDIS_STATUS_FAILURE;
1611 }
1612 }
1613 // handle AES decryption
1614 else if (GroupCipher == Ndis802_11Encryption3Enabled)
1615 {
1616 if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
1617 {
1618
1619 //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
1620 pRxWI->MPDUtotalByteCount -= 16;
1621 }
1622 else
1623 {
1624 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
1625 // give up this frame
1626 return NDIS_STATUS_FAILURE;
1627 }
1628 }
1629 else
1630 {
1631 // give up this frame
1632 return NDIS_STATUS_FAILURE;
1633 }
1634
1635 return NDIS_STATUS_SUCCESS;
1636
1637 }
1638
This page took 0.090115 seconds and 6 git commands to generate.