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