xref: /openbmc/linux/drivers/staging/vt6655/key.c (revision bfd7a281)
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 Variables  --------------------------*/
48 static int msglevel = MSG_LEVEL_INFO;
49 /*---------------------  Static Functions  --------------------------*/
50 
51 /*---------------------  Export Variables  --------------------------*/
52 
53 /*---------------------  Static Definitions -------------------------*/
54 
55 /*---------------------  Static Classes  ----------------------------*/
56 
57 /*---------------------  Static Variables  --------------------------*/
58 
59 /*---------------------  Static Functions  --------------------------*/
60 static void
61 s_vCheckKeyTableValid(PSKeyManagement pTable, void __iomem *dwIoBase)
62 {
63 	int i;
64 
65 	for (i = 0; i < MAX_KEY_TABLE; i++) {
66 		if (pTable->KeyTable[i].bInUse &&
67 		    !pTable->KeyTable[i].PairwiseKey.bKeyValid &&
68 		    !pTable->KeyTable[i].GroupKey[0].bKeyValid &&
69 		    !pTable->KeyTable[i].GroupKey[1].bKeyValid &&
70 		    !pTable->KeyTable[i].GroupKey[2].bKeyValid &&
71 		    !pTable->KeyTable[i].GroupKey[3].bKeyValid) {
72 			pTable->KeyTable[i].bInUse = false;
73 			pTable->KeyTable[i].wKeyCtl = 0;
74 			pTable->KeyTable[i].bSoftWEP = false;
75 			MACvDisableKeyEntry(dwIoBase, i);
76 		}
77 	}
78 }
79 
80 /*---------------------  Export Functions  --------------------------*/
81 
82 /*
83  * Description: Init Key management table
84  *
85  * Parameters:
86  *  In:
87  *      pTable          - Pointer to Key table
88  *  Out:
89  *      none
90  *
91  * Return Value: none
92  *
93  */
94 void KeyvInitTable(PSKeyManagement pTable, void __iomem *dwIoBase)
95 {
96 	int i;
97 	int jj;
98 
99 	for (i = 0; i < MAX_KEY_TABLE; i++) {
100 		pTable->KeyTable[i].bInUse = false;
101 		pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
102 		pTable->KeyTable[i].PairwiseKey.pvKeyTable = (void *)&pTable->KeyTable[i];
103 		for (jj = 0; jj < MAX_GROUP_KEY; jj++) {
104 			pTable->KeyTable[i].GroupKey[jj].bKeyValid = false;
105 			pTable->KeyTable[i].GroupKey[jj].pvKeyTable = (void *)&pTable->KeyTable[i];
106 		}
107 		pTable->KeyTable[i].wKeyCtl = 0;
108 		pTable->KeyTable[i].dwGTKeyIndex = 0;
109 		pTable->KeyTable[i].bSoftWEP = false;
110 		MACvDisableKeyEntry(dwIoBase, i);
111 	}
112 }
113 
114 /*
115  * Description: Get Key from table
116  *
117  * Parameters:
118  *  In:
119  *      pTable          - Pointer to Key table
120  *      pbyBSSID        - BSSID of Key
121  *      dwKeyIndex      - Key Index (0xFFFFFFFF means pairwise key)
122  *  Out:
123  *      pKey            - Key return
124  *
125  * Return Value: true if found otherwise false
126  *
127  */
128 bool KeybGetKey(
129 	PSKeyManagement pTable,
130 	unsigned char *pbyBSSID,
131 	unsigned long dwKeyIndex,
132 	PSKeyItem       *pKey
133 )
134 {
135 	int i;
136 
137 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetKey()\n");
138 
139 	*pKey = NULL;
140 	for (i = 0; i < MAX_KEY_TABLE; i++) {
141 		if (pTable->KeyTable[i].bInUse &&
142 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
143 			if (dwKeyIndex == 0xFFFFFFFF) {
144 				if (pTable->KeyTable[i].PairwiseKey.bKeyValid) {
145 					*pKey = &(pTable->KeyTable[i].PairwiseKey);
146 					return true;
147 				} else {
148 					return false;
149 				}
150 			} else if (dwKeyIndex < MAX_GROUP_KEY) {
151 				if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid) {
152 					*pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]);
153 					return true;
154 				} else {
155 					return false;
156 				}
157 			} else {
158 				return false;
159 			}
160 		}
161 	}
162 	return false;
163 }
164 
165 /*
166  * Description: Set Key to table
167  *
168  * Parameters:
169  *  In:
170  *      pTable          - Pointer to Key table
171  *      pbyBSSID        - BSSID of Key
172  *      dwKeyIndex      - Key index (reference to NDIS DDK)
173  *      uKeyLength      - Key length
174  *      KeyRSC          - Key RSC
175  *      pbyKey          - Pointer to key
176  *  Out:
177  *      none
178  *
179  * Return Value: true if success otherwise false
180  *
181  */
182 bool KeybSetKey(
183 	PSKeyManagement pTable,
184 	unsigned char *pbyBSSID,
185 	unsigned long dwKeyIndex,
186 	unsigned long uKeyLength,
187 	PQWORD          pKeyRSC,
188 	unsigned char *pbyKey,
189 	unsigned char byKeyDecMode,
190 	void __iomem *dwIoBase,
191 	unsigned char byLocalID
192 )
193 {
194 	int i, j;
195 	unsigned int ii;
196 	PSKeyItem   pKey;
197 	unsigned int uKeyIdx;
198 
199 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetKey: %lX\n", dwKeyIndex);
200 
201 	j = (MAX_KEY_TABLE-1);
202 	for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
203 		if (!pTable->KeyTable[i].bInUse && (j == (MAX_KEY_TABLE-1))) {
204 			// found empty table
205 			j = i;
206 		}
207 		if (pTable->KeyTable[i].bInUse &&
208 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
209 			// found table already exist
210 			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
211 				// Pairwise key
212 				pKey = &(pTable->KeyTable[i].PairwiseKey);
213 				pTable->KeyTable[i].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
214 				pTable->KeyTable[i].wKeyCtl |= byKeyDecMode;
215 				uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
216 			} else {
217 				// Group key
218 				if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
219 					return false;
220 				pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
221 				if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
222 					// Group transmit key
223 					pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
224 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
225 				}
226 				pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
227 				pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
228 				pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
229 				uKeyIdx = (dwKeyIndex & 0x000000FF);
230 			}
231 			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
232 
233 			pKey->bKeyValid = true;
234 			pKey->uKeyLength = uKeyLength;
235 			pKey->dwKeyIndex = dwKeyIndex;
236 			pKey->byCipherSuite = byKeyDecMode;
237 			memcpy(pKey->abyKey, pbyKey, uKeyLength);
238 			if (byKeyDecMode == KEY_CTL_WEP) {
239 				if (uKeyLength == WLAN_WEP40_KEYLEN)
240 					pKey->abyKey[15] &= 0x7F;
241 				if (uKeyLength == WLAN_WEP104_KEYLEN)
242 					pKey->abyKey[15] |= 0x80;
243 			}
244 			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey, byLocalID);
245 
246 			if ((dwKeyIndex & USE_KEYRSC) == 0) {
247 				// RSC set by NIC
248 				memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
249 			} else {
250 				memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
251 			}
252 			pKey->dwTSC47_16 = 0;
253 			pKey->wTSC15_0 = 0;
254 
255 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R):\n");
256 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
257 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
258 			for (ii = 0; ii < pKey->uKeyLength; ii++)
259 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
260 
261 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
262 
263 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
264 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
265 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
266 
267 			return true;
268 		}
269 	}
270 	if (j < (MAX_KEY_TABLE-1)) {
271 		memcpy(pTable->KeyTable[j].abyBSSID, pbyBSSID, ETH_ALEN);
272 		pTable->KeyTable[j].bInUse = true;
273 		if ((dwKeyIndex & PAIRWISE_KEY) != 0)  {
274 			// Pairwise key
275 			pKey = &(pTable->KeyTable[j].PairwiseKey);
276 			pTable->KeyTable[j].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
277 			pTable->KeyTable[j].wKeyCtl |= byKeyDecMode;
278 			uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
279 		} else {
280 			// Group key
281 			if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
282 				return false;
283 			pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]);
284 			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
285 				// Group transmit key
286 				pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex;
287 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(N)[%lX]: %d\n", 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 			memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
312 		} else {
313 			memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
314 		}
315 		pKey->dwTSC47_16 = 0;
316 		pKey->wTSC15_0 = 0;
317 
318 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(N):\n");
319 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
320 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
321 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
322 		for (ii = 0; ii < pKey->uKeyLength; ii++)
323 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
324 
325 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
326 
327 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
328 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
329 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "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  */
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  */
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  */
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 
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  */
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 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:");
515 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PAIRWISE_KEY: KeyTable.abyBSSID: ");
516 					for (ii = 0; ii < 6; ii++)
517 						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x ", pTable->KeyTable[i].abyBSSID[ii]);
518 
519 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
520 
521 					return true;
522 				} else {
523 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PairwiseKey.bKeyValid == false\n");
524 					return false;
525 				}
526 			} // End of Type == PAIRWISE
527 			else {
528 				if (pTable->KeyTable[i].dwGTKeyIndex == 0) {
529 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: dwGTKeyIndex == 0 !!!\n");
530 					return false;
531 				}
532 				if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid) {
533 					*pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]);
534 
535 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:");
536 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP_KEY: KeyTable.abyBSSID\n");
537 					for (ii = 0; ii < 6; ii++)
538 						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x ", pTable->KeyTable[i].abyBSSID[ii]);
539 
540 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
541 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex);
542 
543 					return true;
544 				} else {
545 					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GroupKey.bKeyValid == false\n");
546 					return false;
547 				}
548 			} // End of Type = GROUP
549 		} // BSSID match
550 	}
551 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: NO Match BSSID !!! ");
552 	for (ii = 0; ii < 6; ii++)
553 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *(pbyBSSID+ii));
554 
555 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
556 	return false;
557 }
558 
559 /*
560  * Description: Check Pairewise Key
561  *
562  * Parameters:
563  *  In:
564  *      pTable          - Pointer to Key table
565  *  Out:
566  *      none
567  *
568  * Return Value: true if found otherwise false
569  *
570  */
571 bool KeybCheckPairewiseKey(
572 	PSKeyManagement pTable,
573 	PSKeyItem       *pKey
574 )
575 {
576 	int i;
577 
578 	*pKey = NULL;
579 	for (i = 0; i < MAX_KEY_TABLE; i++) {
580 		if (pTable->KeyTable[i].bInUse &&
581 		    pTable->KeyTable[i].PairwiseKey.bKeyValid) {
582 			*pKey = &(pTable->KeyTable[i].PairwiseKey);
583 			return true;
584 		}
585 	}
586 	return false;
587 }
588 
589 /*
590  * Description: Set Key to table
591  *
592  * Parameters:
593  *  In:
594  *      pTable          - Pointer to Key table
595  *      dwKeyIndex      - Key index (reference to NDIS DDK)
596  *      uKeyLength      - Key length
597  *      KeyRSC          - Key RSC
598  *      pbyKey          - Pointer to key
599  *  Out:
600  *      none
601  *
602  * Return Value: true if success otherwise false
603  *
604  */
605 bool KeybSetDefaultKey(
606 	PSKeyManagement pTable,
607 	unsigned long dwKeyIndex,
608 	unsigned long uKeyLength,
609 	PQWORD          pKeyRSC,
610 	unsigned char *pbyKey,
611 	unsigned char byKeyDecMode,
612 	void __iomem *dwIoBase,
613 	unsigned char byLocalID
614 )
615 {
616 	unsigned int ii;
617 	PSKeyItem   pKey;
618 	unsigned int uKeyIdx;
619 
620 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetDefaultKey: %1x, %d\n", (int)dwKeyIndex, (int)uKeyLength);
621 
622 	if ((dwKeyIndex & PAIRWISE_KEY) != 0) // Pairwise key
623 		return false;
624 	else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
625 		return false;
626 
627 	if (uKeyLength > MAX_KEY_LEN)
628 		return false;
629 
630 	pTable->KeyTable[MAX_KEY_TABLE - 1].bInUse = true;
631 	for (ii = 0; ii < ETH_ALEN; ii++)
632 		pTable->KeyTable[MAX_KEY_TABLE - 1].abyBSSID[ii] = 0xFF;
633 
634 	// Group key
635 	pKey = &(pTable->KeyTable[MAX_KEY_TABLE - 1].GroupKey[dwKeyIndex & 0x000000FF]);
636 	if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
637 		// Group transmit key
638 		pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
639 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1);
640 
641 	}
642 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00;          // clear all key control filed
643 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4);
644 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode);
645 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044;          // use group key for all address
646 	uKeyIdx = (dwKeyIndex & 0x000000FF);
647 
648 	if ((uKeyLength == WLAN_WEP232_KEYLEN) &&
649 	    (byKeyDecMode == KEY_CTL_WEP)) {
650 		pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000;              // disable on-fly disable address match
651 		pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true;
652 	} else {
653 		if (!pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP)
654 			pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000;          // enable on-fly disable address match
655 	}
656 
657 	pKey->bKeyValid = true;
658 	pKey->uKeyLength = uKeyLength;
659 	pKey->dwKeyIndex = dwKeyIndex;
660 	pKey->byCipherSuite = byKeyDecMode;
661 	memcpy(pKey->abyKey, pbyKey, uKeyLength);
662 	if (byKeyDecMode == KEY_CTL_WEP) {
663 		if (uKeyLength == WLAN_WEP40_KEYLEN)
664 			pKey->abyKey[15] &= 0x7F;
665 		if (uKeyLength == WLAN_WEP104_KEYLEN)
666 			pKey->abyKey[15] |= 0x80;
667 	}
668 	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);
669 
670 	if ((dwKeyIndex & USE_KEYRSC) == 0) {
671 		// RSC set by NIC
672 		memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
673 	} else {
674 		memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
675 	}
676 	pKey->dwTSC47_16 = 0;
677 	pKey->wTSC15_0 = 0;
678 
679 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R):\n");
680 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n", pKey->bKeyValid);
681 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
682 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey:\n");
683 	for (ii = 0; ii < pKey->uKeyLength; ii++)
684 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x", pKey->abyKey[ii]);
685 
686 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
687 
688 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
689 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
690 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
691 
692 	return true;
693 }
694 
695 /*
696  * Description: Set Key to table
697  *
698  * Parameters:
699  *  In:
700  *      pTable          - Pointer to Key table
701  *      dwKeyIndex      - Key index (reference to NDIS DDK)
702  *      uKeyLength      - Key length
703  *      KeyRSC          - Key RSC
704  *      pbyKey          - Pointer to key
705  *  Out:
706  *      none
707  *
708  * Return Value: true if success otherwise false
709  *
710  */
711 bool KeybSetAllGroupKey(
712 	PSKeyManagement pTable,
713 	unsigned long dwKeyIndex,
714 	unsigned long uKeyLength,
715 	PQWORD          pKeyRSC,
716 	unsigned char *pbyKey,
717 	unsigned char byKeyDecMode,
718 	void __iomem *dwIoBase,
719 	unsigned char byLocalID
720 )
721 {
722 	int         i;
723 	unsigned int ii;
724 	PSKeyItem   pKey;
725 	unsigned int uKeyIdx;
726 
727 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
728 
729 	if ((dwKeyIndex & PAIRWISE_KEY) != 0) // Pairwise key
730 		return false;
731 	else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
732 		return false;
733 
734 	for (i = 0; i < MAX_KEY_TABLE - 1; i++) {
735 		if (pTable->KeyTable[i].bInUse) {
736 			// found table already exist
737 			// Group key
738 			pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
739 			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
740 				// Group transmit key
741 				pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
742 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
743 
744 			}
745 			pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
746 			pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
747 			pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
748 			uKeyIdx = (dwKeyIndex & 0x000000FF);
749 
750 			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
751 
752 			pKey->bKeyValid = true;
753 			pKey->uKeyLength = uKeyLength;
754 			pKey->dwKeyIndex = dwKeyIndex;
755 			pKey->byCipherSuite = byKeyDecMode;
756 			memcpy(pKey->abyKey, pbyKey, uKeyLength);
757 			if (byKeyDecMode == KEY_CTL_WEP) {
758 				if (uKeyLength == WLAN_WEP40_KEYLEN)
759 					pKey->abyKey[15] &= 0x7F;
760 				if (uKeyLength == WLAN_WEP104_KEYLEN)
761 					pKey->abyKey[15] |= 0x80;
762 			}
763 			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (u32 *)pKey->abyKey, byLocalID);
764 
765 			if ((dwKeyIndex & USE_KEYRSC) == 0) {
766 				// RSC set by NIC
767 				memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
768 			} else {
769 				memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
770 			}
771 			pKey->dwTSC47_16 = 0;
772 			pKey->wTSC15_0 = 0;
773 
774 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R):\n");
775 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
776 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
777 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
778 			for (ii = 0; ii < pKey->uKeyLength; ii++)
779 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
780 
781 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
782 
783 		} // (pTable->KeyTable[i].bInUse == true)
784 	}
785 	return true;
786 }
787