• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  *
20  * File: key.c
21  *
22  * Purpose: Implement functions for 802.11i Key management
23  *
24  * Author: Jerry Chen
25  *
26  * Date: May 29, 2003
27  *
28  * Functions:
29  *      KeyvInitTable - Init Key management table
30  *      KeybGetKey - Get Key from table
31  *      KeybSetKey - Set Key to table
32  *      KeybRemoveKey - Remove Key from table
33  *      KeybGetTransmitKey - Get Transmit Key from table
34  *
35  * Revision History:
36  *
37  */
38 
39 #include "tmacro.h"
40 #include "key.h"
41 #include "mac.h"
42 
43 /*---------------------  Static Definitions -------------------------*/
44 
45 /*---------------------  Static Classes  ----------------------------*/
46 
47 /*---------------------  Static Functions  --------------------------*/
48 
49 /*---------------------  Export Variables  --------------------------*/
50 
51 /*---------------------  Static Definitions -------------------------*/
52 
53 /*---------------------  Static Classes  ----------------------------*/
54 
55 /*---------------------  Static Variables  --------------------------*/
56 
57 /*---------------------  Static Functions  --------------------------*/
58 static void
s_vCheckKeyTableValid(PSKeyManagement pTable,void __iomem * dwIoBase)59 s_vCheckKeyTableValid(PSKeyManagement pTable, void __iomem *dwIoBase)
60 {
61 	int i;
62 
63 	for (i = 0; i < MAX_KEY_TABLE; i++) {
64 		if (pTable->KeyTable[i].bInUse &&
65 		    !pTable->KeyTable[i].PairwiseKey.bKeyValid &&
66 		    !pTable->KeyTable[i].GroupKey[0].bKeyValid &&
67 		    !pTable->KeyTable[i].GroupKey[1].bKeyValid &&
68 		    !pTable->KeyTable[i].GroupKey[2].bKeyValid &&
69 		    !pTable->KeyTable[i].GroupKey[3].bKeyValid) {
70 			pTable->KeyTable[i].bInUse = false;
71 			pTable->KeyTable[i].wKeyCtl = 0;
72 			pTable->KeyTable[i].bSoftWEP = false;
73 			MACvDisableKeyEntry(dwIoBase, i);
74 		}
75 	}
76 }
77 
78 /*---------------------  Export Functions  --------------------------*/
79 
80 /*
81  * Description: Init Key management table
82  *
83  * Parameters:
84  *  In:
85  *      pTable          - Pointer to Key table
86  *  Out:
87  *      none
88  *
89  * Return Value: none
90  *
91  */
KeyvInitTable(PSKeyManagement pTable,void __iomem * dwIoBase)92 void KeyvInitTable(PSKeyManagement pTable, void __iomem *dwIoBase)
93 {
94 	int i;
95 	int jj;
96 
97 	for (i = 0; i < MAX_KEY_TABLE; i++) {
98 		pTable->KeyTable[i].bInUse = false;
99 		pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
100 		pTable->KeyTable[i].PairwiseKey.pvKeyTable = (void *)&pTable->KeyTable[i];
101 		for (jj = 0; jj < MAX_GROUP_KEY; jj++) {
102 			pTable->KeyTable[i].GroupKey[jj].bKeyValid = false;
103 			pTable->KeyTable[i].GroupKey[jj].pvKeyTable = (void *)&pTable->KeyTable[i];
104 		}
105 		pTable->KeyTable[i].wKeyCtl = 0;
106 		pTable->KeyTable[i].dwGTKeyIndex = 0;
107 		pTable->KeyTable[i].bSoftWEP = false;
108 		MACvDisableKeyEntry(dwIoBase, i);
109 	}
110 }
111 
112 /*
113  * Description: Get Key from table
114  *
115  * Parameters:
116  *  In:
117  *      pTable          - Pointer to Key table
118  *      pbyBSSID        - BSSID of Key
119  *      dwKeyIndex      - Key Index (0xFFFFFFFF means pairwise key)
120  *  Out:
121  *      pKey            - Key return
122  *
123  * Return Value: true if found otherwise false
124  *
125  */
KeybGetKey(PSKeyManagement pTable,unsigned char * pbyBSSID,unsigned long dwKeyIndex,PSKeyItem * pKey)126 bool KeybGetKey(
127 	PSKeyManagement pTable,
128 	unsigned char *pbyBSSID,
129 	unsigned long dwKeyIndex,
130 	PSKeyItem       *pKey
131 )
132 {
133 	int i;
134 
135 	pr_debug("KeybGetKey()\n");
136 
137 	*pKey = NULL;
138 	for (i = 0; i < MAX_KEY_TABLE; i++) {
139 		if (pTable->KeyTable[i].bInUse &&
140 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
141 			if (dwKeyIndex == 0xFFFFFFFF) {
142 				if (pTable->KeyTable[i].PairwiseKey.bKeyValid) {
143 					*pKey = &(pTable->KeyTable[i].PairwiseKey);
144 					return true;
145 				} else {
146 					return false;
147 				}
148 			} else if (dwKeyIndex < MAX_GROUP_KEY) {
149 				if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid) {
150 					*pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]);
151 					return true;
152 				} else {
153 					return false;
154 				}
155 			} else {
156 				return false;
157 			}
158 		}
159 	}
160 	return false;
161 }
162 
163 /*
164  * Description: Set Key to table
165  *
166  * Parameters:
167  *  In:
168  *      pTable          - Pointer to Key table
169  *      pbyBSSID        - BSSID of Key
170  *      dwKeyIndex      - Key index (reference to NDIS DDK)
171  *      uKeyLength      - Key length
172  *      KeyRSC          - Key RSC
173  *      pbyKey          - Pointer to key
174  *  Out:
175  *      none
176  *
177  * Return Value: true if success otherwise false
178  *
179  */
KeybSetKey(PSKeyManagement pTable,unsigned char * pbyBSSID,unsigned long dwKeyIndex,unsigned long uKeyLength,u64 * pKeyRSC,unsigned char * pbyKey,unsigned char byKeyDecMode,void __iomem * dwIoBase,unsigned char byLocalID)180 bool KeybSetKey(
181 	PSKeyManagement pTable,
182 	unsigned char *pbyBSSID,
183 	unsigned long dwKeyIndex,
184 	unsigned long uKeyLength,
185 	u64 *pKeyRSC,
186 	unsigned char *pbyKey,
187 	unsigned char byKeyDecMode,
188 	void __iomem *dwIoBase,
189 	unsigned char byLocalID
190 )
191 {
192 	int i, j;
193 	unsigned int ii;
194 	PSKeyItem   pKey;
195 	unsigned int uKeyIdx;
196 
197 	pr_debug("Enter KeybSetKey: %lX\n", dwKeyIndex);
198 
199 	j = (MAX_KEY_TABLE-1);
200 	for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
201 		if (!pTable->KeyTable[i].bInUse && (j == (MAX_KEY_TABLE-1))) {
202 			// found empty table
203 			j = i;
204 		}
205 		if (pTable->KeyTable[i].bInUse &&
206 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
207 			// found table already exist
208 			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
209 				// Pairwise key
210 				pKey = &(pTable->KeyTable[i].PairwiseKey);
211 				pTable->KeyTable[i].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
212 				pTable->KeyTable[i].wKeyCtl |= byKeyDecMode;
213 				uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
214 			} else {
215 				// Group key
216 				if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
217 					return false;
218 				pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
219 				if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
220 					// Group transmit key
221 					pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
222 					pr_debug("Group transmit key(R)[%lX]: %d\n",
223 						 pTable->KeyTable[i].dwGTKeyIndex, i);
224 				}
225 				pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
226 				pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
227 				pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
228 				uKeyIdx = (dwKeyIndex & 0x000000FF);
229 			}
230 			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
231 
232 			pKey->bKeyValid = true;
233 			pKey->uKeyLength = uKeyLength;
234 			pKey->dwKeyIndex = dwKeyIndex;
235 			pKey->byCipherSuite = byKeyDecMode;
236 			memcpy(pKey->abyKey, pbyKey, uKeyLength);
237 			if (byKeyDecMode == KEY_CTL_WEP) {
238 				if (uKeyLength == WLAN_WEP40_KEYLEN)
239 					pKey->abyKey[15] &= 0x7F;
240 				if (uKeyLength == WLAN_WEP104_KEYLEN)
241 					pKey->abyKey[15] |= 0x80;
242 			}
243 			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey, byLocalID);
244 
245 			if ((dwKeyIndex & USE_KEYRSC) == 0) {
246 				// RSC set by NIC
247 				pKey->KeyRSC = 0;
248 			} else {
249 				pKey->KeyRSC = *pKeyRSC;
250 			}
251 			pKey->dwTSC47_16 = 0;
252 			pKey->wTSC15_0 = 0;
253 
254 			pr_debug("KeybSetKey(R):\n");
255 			pr_debug("pKey->bKeyValid: %d\n ", pKey->bKeyValid);
256 			pr_debug("pKey->abyKey: ");
257 			for (ii = 0; ii < pKey->uKeyLength; ii++)
258 				pr_debug("%02x ", pKey->abyKey[ii]);
259 
260 			pr_debug("\n");
261 
262 			pr_debug("pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
263 			pr_debug("pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
264 			pr_debug("pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
265 
266 			return true;
267 		}
268 	}
269 	if (j < (MAX_KEY_TABLE-1)) {
270 		memcpy(pTable->KeyTable[j].abyBSSID, pbyBSSID, ETH_ALEN);
271 		pTable->KeyTable[j].bInUse = true;
272 		if ((dwKeyIndex & PAIRWISE_KEY) != 0)  {
273 			// Pairwise key
274 			pKey = &(pTable->KeyTable[j].PairwiseKey);
275 			pTable->KeyTable[j].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
276 			pTable->KeyTable[j].wKeyCtl |= byKeyDecMode;
277 			uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
278 		} else {
279 			// Group key
280 			if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
281 				return false;
282 			pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]);
283 			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
284 				// Group transmit key
285 				pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex;
286 				pr_debug("Group transmit key(N)[%lX]: %d\n",
287 					 pTable->KeyTable[j].dwGTKeyIndex, j);
288 			}
289 			pTable->KeyTable[j].wKeyCtl &= 0xFF0F;          // clear group key control filed
290 			pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4);
291 			pTable->KeyTable[j].wKeyCtl |= 0x0040;          // use group key for group address
292 			uKeyIdx = (dwKeyIndex & 0x000000FF);
293 		}
294 		pTable->KeyTable[j].wKeyCtl |= 0x8000;              // enable on-fly
295 
296 		pKey->bKeyValid = true;
297 		pKey->uKeyLength = uKeyLength;
298 		pKey->dwKeyIndex = dwKeyIndex;
299 		pKey->byCipherSuite = byKeyDecMode;
300 		memcpy(pKey->abyKey, pbyKey, uKeyLength);
301 		if (byKeyDecMode == KEY_CTL_WEP) {
302 			if (uKeyLength == WLAN_WEP40_KEYLEN)
303 				pKey->abyKey[15] &= 0x7F;
304 			if (uKeyLength == WLAN_WEP104_KEYLEN)
305 				pKey->abyKey[15] |= 0x80;
306 		}
307 		MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey, byLocalID);
308 
309 		if ((dwKeyIndex & USE_KEYRSC) == 0) {
310 			// RSC set by NIC
311 			pKey->KeyRSC = 0;
312 		} else {
313 			pKey->KeyRSC = *pKeyRSC;
314 		}
315 		pKey->dwTSC47_16 = 0;
316 		pKey->wTSC15_0 = 0;
317 
318 		pr_debug("KeybSetKey(N):\n");
319 		pr_debug("pKey->bKeyValid: %d\n ", pKey->bKeyValid);
320 		pr_debug("pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
321 		pr_debug("pKey->abyKey: ");
322 		for (ii = 0; ii < pKey->uKeyLength; ii++)
323 			pr_debug("%02x ", pKey->abyKey[ii]);
324 
325 		pr_debug("\n");
326 
327 		pr_debug("pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
328 		pr_debug("pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
329 		pr_debug("pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
330 
331 		return true;
332 	}
333 	return false;
334 }
335 
336 /*
337  * Description: Remove Key from table
338  *
339  * Parameters:
340  *  In:
341  *      pTable          - Pointer to Key table
342  *      pbyBSSID        - BSSID of Key
343  *      dwKeyIndex      - Key Index (reference to NDIS DDK)
344  *  Out:
345  *      none
346  *
347  * Return Value: true if success otherwise false
348  *
349  */
KeybRemoveKey(PSKeyManagement pTable,unsigned char * pbyBSSID,unsigned long dwKeyIndex,void __iomem * dwIoBase)350 bool KeybRemoveKey(
351 	PSKeyManagement pTable,
352 	unsigned char *pbyBSSID,
353 	unsigned long dwKeyIndex,
354 	void __iomem *dwIoBase
355 )
356 {
357 	int  i;
358 
359 	if (is_broadcast_ether_addr(pbyBSSID)) {
360 		// delete all keys
361 		if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
362 			for (i = 0; i < MAX_KEY_TABLE; i++)
363 				pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
364 
365 			s_vCheckKeyTableValid(pTable, dwIoBase);
366 			return true;
367 		} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
368 			for (i = 0; i < MAX_KEY_TABLE; i++) {
369 				pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
370 				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
371 					// remove Group transmit key
372 					pTable->KeyTable[i].dwGTKeyIndex = 0;
373 				}
374 			}
375 			s_vCheckKeyTableValid(pTable, dwIoBase);
376 			return true;
377 		} else {
378 			return false;
379 		}
380 	}
381 
382 	for (i = 0; i < MAX_KEY_TABLE; i++) {
383 		if (pTable->KeyTable[i].bInUse &&
384 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
385 			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
386 				pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
387 				s_vCheckKeyTableValid(pTable, dwIoBase);
388 				return true;
389 			} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
390 				pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
391 				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
392 					// remove Group transmit key
393 					pTable->KeyTable[i].dwGTKeyIndex = 0;
394 				}
395 				s_vCheckKeyTableValid(pTable, dwIoBase);
396 				return true;
397 			} else {
398 				return false;
399 			}
400 		}
401 	}
402 	return false;
403 }
404 
405 /*
406  * Description: Remove Key from table
407  *
408  * Parameters:
409  *  In:
410  *      pTable          - Pointer to Key table
411  *      pbyBSSID        - BSSID of Key
412  *  Out:
413  *      none
414  *
415  * Return Value: true if success otherwise false
416  *
417  */
KeybRemoveAllKey(PSKeyManagement pTable,unsigned char * pbyBSSID,void __iomem * dwIoBase)418 bool KeybRemoveAllKey(
419 	PSKeyManagement pTable,
420 	unsigned char *pbyBSSID,
421 	void __iomem *dwIoBase
422 )
423 {
424 	int i, u;
425 
426 	for (i = 0; i < MAX_KEY_TABLE; i++) {
427 		if (pTable->KeyTable[i].bInUse &&
428 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
429 			pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
430 			for (u = 0; u < MAX_GROUP_KEY; u++)
431 				pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
432 
433 			pTable->KeyTable[i].dwGTKeyIndex = 0;
434 			s_vCheckKeyTableValid(pTable, dwIoBase);
435 			return true;
436 		}
437 	}
438 	return false;
439 }
440 
441 /*
442  * Description: Remove WEP Key from table
443  *
444  * Parameters:
445  *  In:
446  *      pTable          - Pointer to Key table
447  *  Out:
448  *      none
449  *
450  * Return Value: true if success otherwise false
451  *
452  */
KeyvRemoveWEPKey(PSKeyManagement pTable,unsigned long dwKeyIndex,void __iomem * dwIoBase)453 void KeyvRemoveWEPKey(
454 	PSKeyManagement pTable,
455 	unsigned long dwKeyIndex,
456 	void __iomem *dwIoBase
457 )
458 {
459 	if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
460 		if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse) {
461 			if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) {
462 				pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
463 				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) {
464 					// remove Group transmit key
465 					pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0;
466 				}
467 			}
468 		}
469 		s_vCheckKeyTableValid(pTable, dwIoBase);
470 	}
471 }
472 
KeyvRemoveAllWEPKey(PSKeyManagement pTable,void __iomem * dwIoBase)473 void KeyvRemoveAllWEPKey(
474 	PSKeyManagement pTable,
475 	void __iomem *dwIoBase
476 )
477 {
478 	int i;
479 
480 	for (i = 0; i < MAX_GROUP_KEY; i++)
481 		KeyvRemoveWEPKey(pTable, i, dwIoBase);
482 }
483 
484 /*
485  * Description: Get Transmit Key from table
486  *
487  * Parameters:
488  *  In:
489  *      pTable          - Pointer to Key table
490  *      pbyBSSID        - BSSID of Key
491  *  Out:
492  *      pKey            - Key return
493  *
494  * Return Value: true if found otherwise false
495  *
496  */
KeybGetTransmitKey(PSKeyManagement pTable,unsigned char * pbyBSSID,unsigned long dwKeyType,PSKeyItem * pKey)497 bool KeybGetTransmitKey(
498 	PSKeyManagement pTable,
499 	unsigned char *pbyBSSID,
500 	unsigned long dwKeyType,
501 	PSKeyItem       *pKey
502 )
503 {
504 	int i, ii;
505 
506 	*pKey = NULL;
507 	for (i = 0; i < MAX_KEY_TABLE; i++) {
508 		if (pTable->KeyTable[i].bInUse &&
509 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
510 			if (dwKeyType == PAIRWISE_KEY) {
511 				if (pTable->KeyTable[i].PairwiseKey.bKeyValid) {
512 					*pKey = &(pTable->KeyTable[i].PairwiseKey);
513 
514 					pr_debug("KeybGetTransmitKey:");
515 					pr_debug("PAIRWISE_KEY: KeyTable.abyBSSID: ");
516 					for (ii = 0; ii < 6; ii++)
517 						pr_debug("%x ",
518 							 pTable->KeyTable[i].abyBSSID[ii]);
519 
520 					pr_debug("\n");
521 
522 					return true;
523 				} else {
524 					pr_debug("PairwiseKey.bKeyValid == false\n");
525 					return false;
526 				}
527 			} // End of Type == PAIRWISE
528 			else {
529 				if (pTable->KeyTable[i].dwGTKeyIndex == 0) {
530 					pr_debug("ERROR: dwGTKeyIndex == 0 !!!\n");
531 					return false;
532 				}
533 				if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid) {
534 					*pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]);
535 
536 					pr_debug("KeybGetTransmitKey:");
537 					pr_debug("GROUP_KEY: KeyTable.abyBSSID\n");
538 					for (ii = 0; ii < 6; ii++)
539 						pr_debug("%x ",
540 							 pTable->KeyTable[i].abyBSSID[ii]);
541 
542 					pr_debug("\n");
543 					pr_debug("dwGTKeyIndex: %lX\n",
544 						 pTable->KeyTable[i].dwGTKeyIndex);
545 
546 					return true;
547 				} else {
548 					pr_debug("GroupKey.bKeyValid == false\n");
549 					return false;
550 				}
551 			} // End of Type = GROUP
552 		} // BSSID match
553 	}
554 	pr_debug("ERROR: NO Match BSSID !!! ");
555 	for (ii = 0; ii < 6; ii++)
556 		pr_debug("%02x ", *(pbyBSSID+ii));
557 
558 	pr_debug("\n");
559 	return false;
560 }
561 
562 /*
563  * Description: Check Pairewise Key
564  *
565  * Parameters:
566  *  In:
567  *      pTable          - Pointer to Key table
568  *  Out:
569  *      none
570  *
571  * Return Value: true if found otherwise false
572  *
573  */
KeybCheckPairewiseKey(PSKeyManagement pTable,PSKeyItem * pKey)574 bool KeybCheckPairewiseKey(
575 	PSKeyManagement pTable,
576 	PSKeyItem       *pKey
577 )
578 {
579 	int i;
580 
581 	*pKey = NULL;
582 	for (i = 0; i < MAX_KEY_TABLE; i++) {
583 		if (pTable->KeyTable[i].bInUse &&
584 		    pTable->KeyTable[i].PairwiseKey.bKeyValid) {
585 			*pKey = &(pTable->KeyTable[i].PairwiseKey);
586 			return true;
587 		}
588 	}
589 	return false;
590 }
591 
592 /*
593  * Description: Set Key to table
594  *
595  * Parameters:
596  *  In:
597  *      pTable          - Pointer to Key table
598  *      dwKeyIndex      - Key index (reference to NDIS DDK)
599  *      uKeyLength      - Key length
600  *      KeyRSC          - Key RSC
601  *      pbyKey          - Pointer to key
602  *  Out:
603  *      none
604  *
605  * Return Value: true if success otherwise false
606  *
607  */
KeybSetDefaultKey(PSKeyManagement pTable,unsigned long dwKeyIndex,unsigned long uKeyLength,u64 * pKeyRSC,unsigned char * pbyKey,unsigned char byKeyDecMode,void __iomem * dwIoBase,unsigned char byLocalID)608 bool KeybSetDefaultKey(
609 	PSKeyManagement pTable,
610 	unsigned long dwKeyIndex,
611 	unsigned long uKeyLength,
612 	u64 *pKeyRSC,
613 	unsigned char *pbyKey,
614 	unsigned char byKeyDecMode,
615 	void __iomem *dwIoBase,
616 	unsigned char byLocalID
617 )
618 {
619 	unsigned int ii;
620 	PSKeyItem   pKey;
621 	unsigned int uKeyIdx;
622 
623 	pr_debug("Enter KeybSetDefaultKey: %1x, %d\n",
624 		 (int)dwKeyIndex, (int)uKeyLength);
625 
626 	if ((dwKeyIndex & PAIRWISE_KEY) != 0) // Pairwise key
627 		return false;
628 	else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
629 		return false;
630 
631 	if (uKeyLength > MAX_KEY_LEN)
632 		return false;
633 
634 	pTable->KeyTable[MAX_KEY_TABLE - 1].bInUse = true;
635 	for (ii = 0; ii < ETH_ALEN; ii++)
636 		pTable->KeyTable[MAX_KEY_TABLE - 1].abyBSSID[ii] = 0xFF;
637 
638 	// Group key
639 	pKey = &(pTable->KeyTable[MAX_KEY_TABLE - 1].GroupKey[dwKeyIndex & 0x000000FF]);
640 	if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
641 		// Group transmit key
642 		pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
643 		pr_debug("Group transmit key(R)[%lX]: %d\n",
644 			 pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex,
645 			 MAX_KEY_TABLE-1);
646 
647 	}
648 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00;          // clear all key control filed
649 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4);
650 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode);
651 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044;          // use group key for all address
652 	uKeyIdx = (dwKeyIndex & 0x000000FF);
653 
654 	if ((uKeyLength == WLAN_WEP232_KEYLEN) &&
655 	    (byKeyDecMode == KEY_CTL_WEP)) {
656 		pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000;              // disable on-fly disable address match
657 		pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true;
658 	} else {
659 		if (!pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP)
660 			pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000;          // enable on-fly disable address match
661 	}
662 
663 	pKey->bKeyValid = true;
664 	pKey->uKeyLength = uKeyLength;
665 	pKey->dwKeyIndex = dwKeyIndex;
666 	pKey->byCipherSuite = byKeyDecMode;
667 	memcpy(pKey->abyKey, pbyKey, uKeyLength);
668 	if (byKeyDecMode == KEY_CTL_WEP) {
669 		if (uKeyLength == WLAN_WEP40_KEYLEN)
670 			pKey->abyKey[15] &= 0x7F;
671 		if (uKeyLength == WLAN_WEP104_KEYLEN)
672 			pKey->abyKey[15] |= 0x80;
673 	}
674 	MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (u32 *)pKey->abyKey, byLocalID);
675 
676 	if ((dwKeyIndex & USE_KEYRSC) == 0) {
677 		// RSC set by NIC
678 		pKey->KeyRSC = 0;
679 	} else {
680 		pKey->KeyRSC = *pKeyRSC;
681 	}
682 	pKey->dwTSC47_16 = 0;
683 	pKey->wTSC15_0 = 0;
684 
685 	pr_debug("KeybSetKey(R):\n");
686 	pr_debug("pKey->bKeyValid: %d\n", pKey->bKeyValid);
687 	pr_debug("pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
688 	pr_debug("pKey->abyKey:\n");
689 	for (ii = 0; ii < pKey->uKeyLength; ii++)
690 		pr_debug("%x", pKey->abyKey[ii]);
691 
692 	pr_debug("\n");
693 
694 	pr_debug("pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
695 	pr_debug("pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
696 	pr_debug("pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
697 
698 	return true;
699 }
700 
701 /*
702  * Description: Set Key to table
703  *
704  * Parameters:
705  *  In:
706  *      pTable          - Pointer to Key table
707  *      dwKeyIndex      - Key index (reference to NDIS DDK)
708  *      uKeyLength      - Key length
709  *      KeyRSC          - Key RSC
710  *      pbyKey          - Pointer to key
711  *  Out:
712  *      none
713  *
714  * Return Value: true if success otherwise false
715  *
716  */
KeybSetAllGroupKey(PSKeyManagement pTable,unsigned long dwKeyIndex,unsigned long uKeyLength,u64 * pKeyRSC,unsigned char * pbyKey,unsigned char byKeyDecMode,void __iomem * dwIoBase,unsigned char byLocalID)717 bool KeybSetAllGroupKey(
718 	PSKeyManagement pTable,
719 	unsigned long dwKeyIndex,
720 	unsigned long uKeyLength,
721 	u64 *pKeyRSC,
722 	unsigned char *pbyKey,
723 	unsigned char byKeyDecMode,
724 	void __iomem *dwIoBase,
725 	unsigned char byLocalID
726 )
727 {
728 	int         i;
729 	unsigned int ii;
730 	PSKeyItem   pKey;
731 	unsigned int uKeyIdx;
732 
733 	pr_debug("Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
734 
735 	if ((dwKeyIndex & PAIRWISE_KEY) != 0) // Pairwise key
736 		return false;
737 	else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
738 		return false;
739 
740 	for (i = 0; i < MAX_KEY_TABLE - 1; i++) {
741 		if (pTable->KeyTable[i].bInUse) {
742 			// found table already exist
743 			// Group key
744 			pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
745 			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
746 				// Group transmit key
747 				pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
748 				pr_debug("Group transmit key(R)[%lX]: %d\n",
749 					 pTable->KeyTable[i].dwGTKeyIndex, i);
750 
751 			}
752 			pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
753 			pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
754 			pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
755 			uKeyIdx = (dwKeyIndex & 0x000000FF);
756 
757 			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
758 
759 			pKey->bKeyValid = true;
760 			pKey->uKeyLength = uKeyLength;
761 			pKey->dwKeyIndex = dwKeyIndex;
762 			pKey->byCipherSuite = byKeyDecMode;
763 			memcpy(pKey->abyKey, pbyKey, uKeyLength);
764 			if (byKeyDecMode == KEY_CTL_WEP) {
765 				if (uKeyLength == WLAN_WEP40_KEYLEN)
766 					pKey->abyKey[15] &= 0x7F;
767 				if (uKeyLength == WLAN_WEP104_KEYLEN)
768 					pKey->abyKey[15] |= 0x80;
769 			}
770 			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (u32 *)pKey->abyKey, byLocalID);
771 
772 			if ((dwKeyIndex & USE_KEYRSC) == 0) {
773 				// RSC set by NIC
774 				pKey->KeyRSC = 0;
775 			} else {
776 				pKey->KeyRSC = *pKeyRSC;
777 			}
778 			pKey->dwTSC47_16 = 0;
779 			pKey->wTSC15_0 = 0;
780 
781 			pr_debug("KeybSetKey(R):\n");
782 			pr_debug("pKey->bKeyValid: %d\n ", pKey->bKeyValid);
783 			pr_debug("pKey->uKeyLength: %d\n ",
784 				 (int)pKey->uKeyLength);
785 			pr_debug("pKey->abyKey: ");
786 			for (ii = 0; ii < pKey->uKeyLength; ii++)
787 				pr_debug("%02x ", pKey->abyKey[ii]);
788 
789 			pr_debug("\n");
790 
791 		} // (pTable->KeyTable[i].bInUse == true)
792 	}
793 	return true;
794 }
795