xref: /openbmc/linux/drivers/staging/vt6655/key.c (revision 0c074871)
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
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  */
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  */
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  */
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  */
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 		}
378 		return false;
379 	}
380 
381 	for (i = 0; i < MAX_KEY_TABLE; i++) {
382 		if (pTable->KeyTable[i].bInUse &&
383 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
384 			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
385 				pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
386 				s_vCheckKeyTableValid(pTable, dwIoBase);
387 				return true;
388 			} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
389 				pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
390 				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
391 					// remove Group transmit key
392 					pTable->KeyTable[i].dwGTKeyIndex = 0;
393 				}
394 				s_vCheckKeyTableValid(pTable, dwIoBase);
395 				return true;
396 			}
397 			return false;
398 		}
399 	}
400 	return false;
401 }
402 
403 /*
404  * Description: Remove Key from table
405  *
406  * Parameters:
407  *  In:
408  *      pTable          - Pointer to Key table
409  *      pbyBSSID        - BSSID of Key
410  *  Out:
411  *      none
412  *
413  * Return Value: true if success otherwise false
414  *
415  */
416 bool KeybRemoveAllKey(
417 	PSKeyManagement pTable,
418 	unsigned char *pbyBSSID,
419 	void __iomem *dwIoBase
420 )
421 {
422 	int i, u;
423 
424 	for (i = 0; i < MAX_KEY_TABLE; i++) {
425 		if (pTable->KeyTable[i].bInUse &&
426 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
427 			pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
428 			for (u = 0; u < MAX_GROUP_KEY; u++)
429 				pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
430 
431 			pTable->KeyTable[i].dwGTKeyIndex = 0;
432 			s_vCheckKeyTableValid(pTable, dwIoBase);
433 			return true;
434 		}
435 	}
436 	return false;
437 }
438 
439 /*
440  * Description: Remove WEP Key from table
441  *
442  * Parameters:
443  *  In:
444  *      pTable          - Pointer to Key table
445  *  Out:
446  *      none
447  *
448  * Return Value: true if success otherwise false
449  *
450  */
451 void KeyvRemoveWEPKey(
452 	PSKeyManagement pTable,
453 	unsigned long dwKeyIndex,
454 	void __iomem *dwIoBase
455 )
456 {
457 	if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
458 		if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse) {
459 			if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) {
460 				pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
461 				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) {
462 					// remove Group transmit key
463 					pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0;
464 				}
465 			}
466 		}
467 		s_vCheckKeyTableValid(pTable, dwIoBase);
468 	}
469 }
470 
471 void KeyvRemoveAllWEPKey(
472 	PSKeyManagement pTable,
473 	void __iomem *dwIoBase
474 )
475 {
476 	int i;
477 
478 	for (i = 0; i < MAX_GROUP_KEY; i++)
479 		KeyvRemoveWEPKey(pTable, i, dwIoBase);
480 }
481 
482 /*
483  * Description: Get Transmit Key from table
484  *
485  * Parameters:
486  *  In:
487  *      pTable          - Pointer to Key table
488  *      pbyBSSID        - BSSID of Key
489  *  Out:
490  *      pKey            - Key return
491  *
492  * Return Value: true if found otherwise false
493  *
494  */
495 bool KeybGetTransmitKey(
496 	PSKeyManagement pTable,
497 	unsigned char *pbyBSSID,
498 	unsigned long dwKeyType,
499 	PSKeyItem       *pKey
500 )
501 {
502 	int i, ii;
503 
504 	*pKey = NULL;
505 	for (i = 0; i < MAX_KEY_TABLE; i++) {
506 		if (pTable->KeyTable[i].bInUse &&
507 		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
508 			if (dwKeyType == PAIRWISE_KEY) {
509 				if (pTable->KeyTable[i].PairwiseKey.bKeyValid) {
510 					*pKey = &(pTable->KeyTable[i].PairwiseKey);
511 
512 					pr_debug("KeybGetTransmitKey:");
513 					pr_debug("PAIRWISE_KEY: KeyTable.abyBSSID: ");
514 					for (ii = 0; ii < 6; ii++)
515 						pr_debug("%x ",
516 							 pTable->KeyTable[i].abyBSSID[ii]);
517 
518 					pr_debug("\n");
519 
520 					return true;
521 				} else {
522 					pr_debug("PairwiseKey.bKeyValid == false\n");
523 					return false;
524 				}
525 			} // End of Type == PAIRWISE
526 			else {
527 				if (pTable->KeyTable[i].dwGTKeyIndex == 0) {
528 					pr_debug("ERROR: dwGTKeyIndex == 0 !!!\n");
529 					return false;
530 				}
531 				if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid) {
532 					*pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]);
533 
534 					pr_debug("KeybGetTransmitKey:");
535 					pr_debug("GROUP_KEY: KeyTable.abyBSSID\n");
536 					for (ii = 0; ii < 6; ii++)
537 						pr_debug("%x ",
538 							 pTable->KeyTable[i].abyBSSID[ii]);
539 
540 					pr_debug("\n");
541 					pr_debug("dwGTKeyIndex: %lX\n",
542 						 pTable->KeyTable[i].dwGTKeyIndex);
543 
544 					return true;
545 				} else {
546 					pr_debug("GroupKey.bKeyValid == false\n");
547 					return false;
548 				}
549 			} // End of Type = GROUP
550 		} // BSSID match
551 	}
552 	pr_debug("ERROR: NO Match BSSID !!! ");
553 	for (ii = 0; ii < 6; ii++)
554 		pr_debug("%02x ", *(pbyBSSID+ii));
555 
556 	pr_debug("\n");
557 	return false;
558 }
559 
560 /*
561  * Description: Check Pairewise Key
562  *
563  * Parameters:
564  *  In:
565  *      pTable          - Pointer to Key table
566  *  Out:
567  *      none
568  *
569  * Return Value: true if found otherwise false
570  *
571  */
572 bool KeybCheckPairewiseKey(
573 	PSKeyManagement pTable,
574 	PSKeyItem       *pKey
575 )
576 {
577 	int i;
578 
579 	*pKey = NULL;
580 	for (i = 0; i < MAX_KEY_TABLE; i++) {
581 		if (pTable->KeyTable[i].bInUse &&
582 		    pTable->KeyTable[i].PairwiseKey.bKeyValid) {
583 			*pKey = &(pTable->KeyTable[i].PairwiseKey);
584 			return true;
585 		}
586 	}
587 	return false;
588 }
589 
590 /*
591  * Description: Set Key to table
592  *
593  * Parameters:
594  *  In:
595  *      pTable          - Pointer to Key table
596  *      dwKeyIndex      - Key index (reference to NDIS DDK)
597  *      uKeyLength      - Key length
598  *      KeyRSC          - Key RSC
599  *      pbyKey          - Pointer to key
600  *  Out:
601  *      none
602  *
603  * Return Value: true if success otherwise false
604  *
605  */
606 bool KeybSetDefaultKey(
607 	PSKeyManagement pTable,
608 	unsigned long dwKeyIndex,
609 	unsigned long uKeyLength,
610 	u64 *pKeyRSC,
611 	unsigned char *pbyKey,
612 	unsigned char byKeyDecMode,
613 	void __iomem *dwIoBase,
614 	unsigned char byLocalID
615 )
616 {
617 	unsigned int ii;
618 	PSKeyItem   pKey;
619 	unsigned int uKeyIdx;
620 
621 	pr_debug("Enter KeybSetDefaultKey: %1x, %d\n",
622 		 (int)dwKeyIndex, (int)uKeyLength);
623 
624 	if ((dwKeyIndex & PAIRWISE_KEY) != 0) // Pairwise key
625 		return false;
626 	else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
627 		return false;
628 
629 	if (uKeyLength > MAX_KEY_LEN)
630 		return false;
631 
632 	pTable->KeyTable[MAX_KEY_TABLE - 1].bInUse = true;
633 	for (ii = 0; ii < ETH_ALEN; ii++)
634 		pTable->KeyTable[MAX_KEY_TABLE - 1].abyBSSID[ii] = 0xFF;
635 
636 	// Group key
637 	pKey = &(pTable->KeyTable[MAX_KEY_TABLE - 1].GroupKey[dwKeyIndex & 0x000000FF]);
638 	if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
639 		// Group transmit key
640 		pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
641 		pr_debug("Group transmit key(R)[%lX]: %d\n",
642 			 pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex,
643 			 MAX_KEY_TABLE-1);
644 
645 	}
646 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00;          // clear all key control filed
647 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4);
648 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode);
649 	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044;          // use group key for all address
650 	uKeyIdx = (dwKeyIndex & 0x000000FF);
651 
652 	if ((uKeyLength == WLAN_WEP232_KEYLEN) &&
653 	    (byKeyDecMode == KEY_CTL_WEP)) {
654 		pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000;              // disable on-fly disable address match
655 		pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true;
656 	} else {
657 		if (!pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP)
658 			pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000;          // enable on-fly disable address match
659 	}
660 
661 	pKey->bKeyValid = true;
662 	pKey->uKeyLength = uKeyLength;
663 	pKey->dwKeyIndex = dwKeyIndex;
664 	pKey->byCipherSuite = byKeyDecMode;
665 	memcpy(pKey->abyKey, pbyKey, uKeyLength);
666 	if (byKeyDecMode == KEY_CTL_WEP) {
667 		if (uKeyLength == WLAN_WEP40_KEYLEN)
668 			pKey->abyKey[15] &= 0x7F;
669 		if (uKeyLength == WLAN_WEP104_KEYLEN)
670 			pKey->abyKey[15] |= 0x80;
671 	}
672 	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);
673 
674 	if ((dwKeyIndex & USE_KEYRSC) == 0) {
675 		// RSC set by NIC
676 		pKey->KeyRSC = 0;
677 	} else {
678 		pKey->KeyRSC = *pKeyRSC;
679 	}
680 	pKey->dwTSC47_16 = 0;
681 	pKey->wTSC15_0 = 0;
682 
683 	pr_debug("KeybSetKey(R):\n");
684 	pr_debug("pKey->bKeyValid: %d\n", pKey->bKeyValid);
685 	pr_debug("pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
686 	pr_debug("pKey->abyKey:\n");
687 	for (ii = 0; ii < pKey->uKeyLength; ii++)
688 		pr_debug("%x", pKey->abyKey[ii]);
689 
690 	pr_debug("\n");
691 
692 	pr_debug("pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
693 	pr_debug("pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
694 	pr_debug("pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
695 
696 	return true;
697 }
698 
699 /*
700  * Description: Set Key to table
701  *
702  * Parameters:
703  *  In:
704  *      pTable          - Pointer to Key table
705  *      dwKeyIndex      - Key index (reference to NDIS DDK)
706  *      uKeyLength      - Key length
707  *      KeyRSC          - Key RSC
708  *      pbyKey          - Pointer to key
709  *  Out:
710  *      none
711  *
712  * Return Value: true if success otherwise false
713  *
714  */
715 bool KeybSetAllGroupKey(
716 	PSKeyManagement pTable,
717 	unsigned long dwKeyIndex,
718 	unsigned long uKeyLength,
719 	u64 *pKeyRSC,
720 	unsigned char *pbyKey,
721 	unsigned char byKeyDecMode,
722 	void __iomem *dwIoBase,
723 	unsigned char byLocalID
724 )
725 {
726 	int         i;
727 	unsigned int ii;
728 	PSKeyItem   pKey;
729 	unsigned int uKeyIdx;
730 
731 	pr_debug("Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
732 
733 	if ((dwKeyIndex & PAIRWISE_KEY) != 0) // Pairwise key
734 		return false;
735 	else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
736 		return false;
737 
738 	for (i = 0; i < MAX_KEY_TABLE - 1; i++) {
739 		if (pTable->KeyTable[i].bInUse) {
740 			// found table already exist
741 			// Group key
742 			pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
743 			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
744 				// Group transmit key
745 				pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
746 				pr_debug("Group transmit key(R)[%lX]: %d\n",
747 					 pTable->KeyTable[i].dwGTKeyIndex, i);
748 
749 			}
750 			pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
751 			pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
752 			pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
753 			uKeyIdx = (dwKeyIndex & 0x000000FF);
754 
755 			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
756 
757 			pKey->bKeyValid = true;
758 			pKey->uKeyLength = uKeyLength;
759 			pKey->dwKeyIndex = dwKeyIndex;
760 			pKey->byCipherSuite = byKeyDecMode;
761 			memcpy(pKey->abyKey, pbyKey, uKeyLength);
762 			if (byKeyDecMode == KEY_CTL_WEP) {
763 				if (uKeyLength == WLAN_WEP40_KEYLEN)
764 					pKey->abyKey[15] &= 0x7F;
765 				if (uKeyLength == WLAN_WEP104_KEYLEN)
766 					pKey->abyKey[15] |= 0x80;
767 			}
768 			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (u32 *)pKey->abyKey, byLocalID);
769 
770 			if ((dwKeyIndex & USE_KEYRSC) == 0) {
771 				// RSC set by NIC
772 				pKey->KeyRSC = 0;
773 			} else {
774 				pKey->KeyRSC = *pKeyRSC;
775 			}
776 			pKey->dwTSC47_16 = 0;
777 			pKey->wTSC15_0 = 0;
778 
779 			pr_debug("KeybSetKey(R):\n");
780 			pr_debug("pKey->bKeyValid: %d\n ", pKey->bKeyValid);
781 			pr_debug("pKey->uKeyLength: %d\n ",
782 				 (int)pKey->uKeyLength);
783 			pr_debug("pKey->abyKey: ");
784 			for (ii = 0; ii < pKey->uKeyLength; ii++)
785 				pr_debug("%02x ", pKey->abyKey[ii]);
786 
787 			pr_debug("\n");
788 
789 		} // (pTable->KeyTable[i].bInUse == true)
790 	}
791 	return true;
792 }
793