Commit | Line | Data |
---|---|---|
92b96797 FB |
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 | ||
11d404cb | 39 | #include "mac.h" |
92b96797 | 40 | #include "tmacro.h" |
92b96797 | 41 | #include "key.h" |
62c8526d | 42 | #include "usbpipe.h" |
92b96797 | 43 | |
92b96797 FB |
44 | static int msglevel =MSG_LEVEL_INFO; |
45 | //static int msglevel =MSG_LEVEL_DEBUG; | |
92b96797 | 46 | |
da033bfd MP |
47 | static void s_vCheckKeyTableValid(struct vnt_private *pDevice, |
48 | PSKeyManagement pTable) | |
92b96797 | 49 | { |
da033bfd MP |
50 | int i; |
51 | u16 wLength = 0; | |
52 | u8 pbyData[MAX_KEY_TABLE]; | |
92b96797 FB |
53 | |
54 | for (i=0;i<MAX_KEY_TABLE;i++) { | |
4e9b5e2b | 55 | if ((pTable->KeyTable[i].bInUse == true) && |
e269fc2d AM |
56 | (pTable->KeyTable[i].PairwiseKey.bKeyValid == false) && |
57 | (pTable->KeyTable[i].GroupKey[0].bKeyValid == false) && | |
58 | (pTable->KeyTable[i].GroupKey[1].bKeyValid == false) && | |
59 | (pTable->KeyTable[i].GroupKey[2].bKeyValid == false) && | |
60 | (pTable->KeyTable[i].GroupKey[3].bKeyValid == false) | |
92b96797 FB |
61 | ) { |
62 | ||
e269fc2d | 63 | pTable->KeyTable[i].bInUse = false; |
92b96797 | 64 | pTable->KeyTable[i].wKeyCtl = 0; |
e269fc2d | 65 | pTable->KeyTable[i].bSoftWEP = false; |
b902fbfe | 66 | pbyData[wLength++] = (u8) i; |
92b96797 FB |
67 | //MACvDisableKeyEntry(pDevice, i); |
68 | } | |
69 | } | |
1390b02a MP |
70 | |
71 | if (wLength != 0) | |
72 | vnt_control_out(pDevice, MESSAGE_TYPE_CLRKEYENTRY, | |
73 | 0, 0, wLength, pbyData); | |
92b96797 FB |
74 | |
75 | } | |
76 | ||
92b96797 FB |
77 | /* |
78 | * Description: Init Key management table | |
79 | * | |
80 | * Parameters: | |
81 | * In: | |
82 | * pTable - Pointer to Key table | |
83 | * Out: | |
84 | * none | |
85 | * | |
86 | * Return Value: none | |
87 | * | |
88 | */ | |
da033bfd | 89 | void KeyvInitTable(struct vnt_private *pDevice, PSKeyManagement pTable) |
92b96797 | 90 | { |
da033bfd MP |
91 | int i, jj; |
92 | u8 pbyData[MAX_KEY_TABLE+1]; | |
92b96797 | 93 | |
92b96797 | 94 | for (i=0;i<MAX_KEY_TABLE;i++) { |
e269fc2d AM |
95 | pTable->KeyTable[i].bInUse = false; |
96 | pTable->KeyTable[i].PairwiseKey.bKeyValid = false; | |
8611a29a AM |
97 | pTable->KeyTable[i].PairwiseKey.pvKeyTable = |
98 | (void *)&pTable->KeyTable[i]; | |
92b96797 | 99 | for (jj=0; jj < MAX_GROUP_KEY; jj++) { |
e269fc2d | 100 | pTable->KeyTable[i].GroupKey[jj].bKeyValid = false; |
8611a29a AM |
101 | pTable->KeyTable[i].GroupKey[jj].pvKeyTable = |
102 | (void *) &(pTable->KeyTable[i]); | |
92b96797 FB |
103 | } |
104 | pTable->KeyTable[i].wKeyCtl = 0; | |
105 | pTable->KeyTable[i].dwGTKeyIndex = 0; | |
e269fc2d | 106 | pTable->KeyTable[i].bSoftWEP = false; |
b902fbfe | 107 | pbyData[i] = (u8) i; |
92b96797 | 108 | } |
b902fbfe | 109 | pbyData[i] = (u8) i; |
1390b02a MP |
110 | |
111 | vnt_control_out(pDevice, MESSAGE_TYPE_CLRKEYENTRY, | |
112 | 0, 0, 11, pbyData); | |
92b96797 | 113 | |
92b96797 FB |
114 | return; |
115 | } | |
116 | ||
92b96797 FB |
117 | /* |
118 | * Description: Get Key from table | |
119 | * | |
120 | * Parameters: | |
121 | * In: | |
122 | * pTable - Pointer to Key table | |
123 | * pbyBSSID - BSSID of Key | |
124 | * dwKeyIndex - Key Index (0xFFFFFFFF means pairwise key) | |
125 | * Out: | |
126 | * pKey - Key return | |
127 | * | |
4e9b5e2b | 128 | * Return Value: true if found otherwise false |
92b96797 FB |
129 | * |
130 | */ | |
da033bfd MP |
131 | int KeybGetKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyIndex, |
132 | PSKeyItem *pKey) | |
92b96797 | 133 | { |
da033bfd | 134 | int i; |
92b96797 | 135 | |
da033bfd | 136 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetKey()\n"); |
92b96797 FB |
137 | |
138 | *pKey = NULL; | |
139 | for (i=0;i<MAX_KEY_TABLE;i++) { | |
4e9b5e2b | 140 | if ((pTable->KeyTable[i].bInUse == true) && |
8329419a | 141 | ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { |
92b96797 | 142 | if (dwKeyIndex == 0xFFFFFFFF) { |
4e9b5e2b | 143 | if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) { |
92b96797 | 144 | *pKey = &(pTable->KeyTable[i].PairwiseKey); |
4e9b5e2b | 145 | return (true); |
92b96797 FB |
146 | } |
147 | else { | |
e269fc2d | 148 | return (false); |
92b96797 FB |
149 | } |
150 | } else if (dwKeyIndex < MAX_GROUP_KEY) { | |
4e9b5e2b | 151 | if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == true) { |
92b96797 | 152 | *pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]); |
4e9b5e2b | 153 | return (true); |
92b96797 FB |
154 | } |
155 | else { | |
e269fc2d | 156 | return (false); |
92b96797 FB |
157 | } |
158 | } | |
159 | else { | |
e269fc2d | 160 | return (false); |
92b96797 FB |
161 | } |
162 | } | |
163 | } | |
e269fc2d | 164 | return (false); |
92b96797 FB |
165 | } |
166 | ||
92b96797 FB |
167 | /* |
168 | * Description: Set Key to table | |
169 | * | |
170 | * Parameters: | |
171 | * In: | |
172 | * pTable - Pointer to Key table | |
173 | * pbyBSSID - BSSID of Key | |
174 | * dwKeyIndex - Key index (reference to NDIS DDK) | |
175 | * uKeyLength - Key length | |
176 | * KeyRSC - Key RSC | |
177 | * pbyKey - Pointer to key | |
178 | * Out: | |
179 | * none | |
180 | * | |
4e9b5e2b | 181 | * Return Value: true if success otherwise false |
92b96797 FB |
182 | * |
183 | */ | |
da033bfd MP |
184 | int KeybSetKey(struct vnt_private *pDevice, PSKeyManagement pTable, |
185 | u8 *pbyBSSID, u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, | |
186 | u8 byKeyDecMode) | |
92b96797 | 187 | { |
da033bfd MP |
188 | PSKeyItem pKey; |
189 | int i, j, ii; | |
190 | u32 uKeyIdx; | |
92b96797 | 191 | |
b4dc03af MP |
192 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
193 | "Enter KeybSetKey: %X\n", dwKeyIndex); | |
92b96797 FB |
194 | |
195 | j = (MAX_KEY_TABLE-1); | |
196 | for (i=0;i<(MAX_KEY_TABLE-1);i++) { | |
e269fc2d | 197 | if ((pTable->KeyTable[i].bInUse == false) && |
92b96797 FB |
198 | (j == (MAX_KEY_TABLE-1))) { |
199 | // found empty table | |
200 | j = i; | |
201 | } | |
4e9b5e2b | 202 | if ((pTable->KeyTable[i].bInUse == true) && |
8329419a | 203 | ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { |
92b96797 FB |
204 | // found table already exist |
205 | if ((dwKeyIndex & PAIRWISE_KEY) != 0) { | |
206 | // Pairwise key | |
207 | pKey = &(pTable->KeyTable[i].PairwiseKey); | |
208 | pTable->KeyTable[i].wKeyCtl &= 0xFFF0; // clear pairwise key control filed | |
209 | pTable->KeyTable[i].wKeyCtl |= byKeyDecMode; | |
210 | uKeyIdx = 4; // use HW key entry 4 for pairwise key | |
211 | } else { | |
212 | // Group key | |
213 | if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) | |
e269fc2d | 214 | return (false); |
92b96797 FB |
215 | pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); |
216 | if ((dwKeyIndex & TRANSMIT_KEY) != 0) { | |
217 | // Group transmit key | |
218 | pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; | |
b4dc03af MP |
219 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
220 | "Group transmit key(R)[%X]: %d\n", | |
221 | pTable->KeyTable[i].dwGTKeyIndex, i); | |
92b96797 FB |
222 | } |
223 | pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed | |
224 | pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); | |
225 | pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address | |
226 | uKeyIdx = (dwKeyIndex & 0x000000FF); | |
227 | } | |
228 | pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly | |
229 | ||
4e9b5e2b | 230 | pKey->bKeyValid = true; |
92b96797 FB |
231 | pKey->uKeyLength = uKeyLength; |
232 | pKey->dwKeyIndex = dwKeyIndex; | |
233 | pKey->byCipherSuite = byKeyDecMode; | |
3e362598 | 234 | memcpy(pKey->abyKey, pbyKey, uKeyLength); |
92b96797 FB |
235 | if (byKeyDecMode == KEY_CTL_WEP) { |
236 | if (uKeyLength == WLAN_WEP40_KEYLEN) | |
237 | pKey->abyKey[15] &= 0x7F; | |
238 | if (uKeyLength == WLAN_WEP104_KEYLEN) | |
239 | pKey->abyKey[15] |= 0x80; | |
240 | } | |
954e8142 MP |
241 | |
242 | MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, | |
243 | pbyBSSID, pKey->abyKey); | |
92b96797 | 244 | |
7c65fa2a MP |
245 | if ((dwKeyIndex & USE_KEYRSC) == 0) |
246 | pKey->KeyRSC = 0; /* RSC set by NIC */ | |
247 | else | |
248 | pKey->KeyRSC = *KeyRSC; | |
249 | ||
92b96797 FB |
250 | pKey->dwTSC47_16 = 0; |
251 | pKey->wTSC15_0 = 0; | |
252 | ||
253 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); | |
254 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); | |
255 | //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", pKey->uKeyLength); | |
256 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); | |
257 | for (ii = 0; ii < pKey->uKeyLength; ii++) { | |
258 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]); | |
259 | } | |
260 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
261 | ||
b4dc03af MP |
262 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", |
263 | pKey->dwTSC47_16); | |
264 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", | |
265 | pKey->wTSC15_0); | |
266 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", | |
267 | pKey->dwKeyIndex); | |
92b96797 | 268 | |
4e9b5e2b | 269 | return (true); |
92b96797 FB |
270 | } |
271 | } | |
272 | if (j < (MAX_KEY_TABLE-1)) { | |
9a0e756c | 273 | memcpy(pTable->KeyTable[j].abyBSSID, pbyBSSID, ETH_ALEN); |
4e9b5e2b | 274 | pTable->KeyTable[j].bInUse = true; |
92b96797 FB |
275 | if ((dwKeyIndex & PAIRWISE_KEY) != 0) { |
276 | // Pairwise key | |
277 | pKey = &(pTable->KeyTable[j].PairwiseKey); | |
278 | pTable->KeyTable[j].wKeyCtl &= 0xFFF0; // clear pairwise key control filed | |
279 | pTable->KeyTable[j].wKeyCtl |= byKeyDecMode; | |
280 | uKeyIdx = 4; // use HW key entry 4 for pairwise key | |
281 | } else { | |
282 | // Group key | |
283 | if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) | |
e269fc2d | 284 | return (false); |
92b96797 FB |
285 | pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]); |
286 | if ((dwKeyIndex & TRANSMIT_KEY) != 0) { | |
287 | // Group transmit key | |
288 | pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; | |
b4dc03af MP |
289 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
290 | "Group transmit key(N)[%X]: %d\n", | |
291 | pTable->KeyTable[j].dwGTKeyIndex, j); | |
92b96797 FB |
292 | } |
293 | pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed | |
294 | pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); | |
295 | pTable->KeyTable[j].wKeyCtl |= 0x0040; // use group key for group address | |
296 | uKeyIdx = (dwKeyIndex & 0x000000FF); | |
297 | } | |
298 | pTable->KeyTable[j].wKeyCtl |= 0x8000; // enable on-fly | |
299 | ||
4e9b5e2b | 300 | pKey->bKeyValid = true; |
92b96797 FB |
301 | pKey->uKeyLength = uKeyLength; |
302 | pKey->dwKeyIndex = dwKeyIndex; | |
303 | pKey->byCipherSuite = byKeyDecMode; | |
3e362598 | 304 | memcpy(pKey->abyKey, pbyKey, uKeyLength); |
92b96797 FB |
305 | if (byKeyDecMode == KEY_CTL_WEP) { |
306 | if (uKeyLength == WLAN_WEP40_KEYLEN) | |
307 | pKey->abyKey[15] &= 0x7F; | |
308 | if (uKeyLength == WLAN_WEP104_KEYLEN) | |
309 | pKey->abyKey[15] |= 0x80; | |
310 | } | |
954e8142 MP |
311 | |
312 | MACvSetKeyEntry(pDevice, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, | |
313 | pbyBSSID, pKey->abyKey); | |
92b96797 | 314 | |
7c65fa2a MP |
315 | if ((dwKeyIndex & USE_KEYRSC) == 0) |
316 | pKey->KeyRSC = 0; /* RSC set by NIC */ | |
317 | else | |
318 | pKey->KeyRSC = *KeyRSC; | |
319 | ||
92b96797 FB |
320 | pKey->dwTSC47_16 = 0; |
321 | pKey->wTSC15_0 = 0; | |
322 | ||
323 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(N): \n"); | |
324 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); | |
325 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength); | |
326 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); | |
327 | for (ii = 0; ii < pKey->uKeyLength; ii++) { | |
328 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]); | |
329 | } | |
330 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
331 | ||
b4dc03af MP |
332 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", |
333 | pKey->dwTSC47_16); | |
92b96797 | 334 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); |
b4dc03af MP |
335 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", |
336 | pKey->dwKeyIndex); | |
92b96797 | 337 | |
4e9b5e2b | 338 | return (true); |
92b96797 | 339 | } |
e269fc2d | 340 | return (false); |
92b96797 FB |
341 | } |
342 | ||
92b96797 FB |
343 | /* |
344 | * Description: Remove Key from table | |
345 | * | |
346 | * Parameters: | |
347 | * In: | |
348 | * pTable - Pointer to Key table | |
349 | * pbyBSSID - BSSID of Key | |
350 | * dwKeyIndex - Key Index (reference to NDIS DDK) | |
351 | * Out: | |
352 | * none | |
353 | * | |
4e9b5e2b | 354 | * Return Value: true if success otherwise false |
92b96797 FB |
355 | * |
356 | */ | |
da033bfd MP |
357 | |
358 | int KeybRemoveKey(struct vnt_private *pDevice, PSKeyManagement pTable, | |
359 | u8 *pbyBSSID, u32 dwKeyIndex) | |
92b96797 | 360 | { |
da033bfd | 361 | int i; |
e269fc2d | 362 | int bReturnValue = false; |
92b96797 | 363 | |
4b50fb40 | 364 | if (is_broadcast_ether_addr(pbyBSSID)) { |
a0a1f61a | 365 | // delete all keys |
92b96797 FB |
366 | if ((dwKeyIndex & PAIRWISE_KEY) != 0) { |
367 | for (i=0;i<MAX_KEY_TABLE;i++) { | |
e269fc2d | 368 | pTable->KeyTable[i].PairwiseKey.bKeyValid = false; |
92b96797 | 369 | } |
4e9b5e2b | 370 | bReturnValue = true; |
92b96797 FB |
371 | } |
372 | else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { | |
373 | for (i=0;i<MAX_KEY_TABLE;i++) { | |
e269fc2d | 374 | pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false; |
92b96797 FB |
375 | if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) { |
376 | // remove Group transmit key | |
377 | pTable->KeyTable[i].dwGTKeyIndex = 0; | |
378 | } | |
379 | } | |
4e9b5e2b | 380 | bReturnValue = true; |
92b96797 FB |
381 | } |
382 | else { | |
e269fc2d | 383 | bReturnValue = false; |
92b96797 FB |
384 | } |
385 | ||
386 | } else { | |
387 | for (i=0;i<MAX_KEY_TABLE;i++) { | |
4e9b5e2b | 388 | if ( (pTable->KeyTable[i].bInUse == true) && |
8329419a | 389 | ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { |
92b96797 FB |
390 | |
391 | if ((dwKeyIndex & PAIRWISE_KEY) != 0) { | |
e269fc2d | 392 | pTable->KeyTable[i].PairwiseKey.bKeyValid = false; |
4e9b5e2b | 393 | bReturnValue = true; |
92b96797 FB |
394 | break; |
395 | } | |
396 | else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { | |
e269fc2d | 397 | pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false; |
92b96797 FB |
398 | if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) { |
399 | // remove Group transmit key | |
400 | pTable->KeyTable[i].dwGTKeyIndex = 0; | |
401 | } | |
4e9b5e2b | 402 | bReturnValue = true; |
92b96797 FB |
403 | break; |
404 | } | |
405 | else { | |
e269fc2d | 406 | bReturnValue = false; |
92b96797 FB |
407 | break; |
408 | } | |
4e9b5e2b | 409 | } //pTable->KeyTable[i].bInUse == true |
92b96797 | 410 | } //for |
4e9b5e2b | 411 | bReturnValue = true; |
92b96797 FB |
412 | } |
413 | ||
414 | s_vCheckKeyTableValid(pDevice,pTable); | |
415 | return bReturnValue; | |
416 | ||
92b96797 FB |
417 | } |
418 | ||
92b96797 FB |
419 | /* |
420 | * Description: Remove Key from table | |
421 | * | |
422 | * Parameters: | |
423 | * In: | |
424 | * pTable - Pointer to Key table | |
425 | * pbyBSSID - BSSID of Key | |
426 | * Out: | |
427 | * none | |
428 | * | |
4e9b5e2b | 429 | * Return Value: true if success otherwise false |
92b96797 FB |
430 | * |
431 | */ | |
da033bfd MP |
432 | int KeybRemoveAllKey(struct vnt_private *pDevice, PSKeyManagement pTable, |
433 | u8 *pbyBSSID) | |
92b96797 | 434 | { |
da033bfd | 435 | int i, u; |
92b96797 FB |
436 | |
437 | for (i=0;i<MAX_KEY_TABLE;i++) { | |
4e9b5e2b | 438 | if ((pTable->KeyTable[i].bInUse == true) && |
8329419a | 439 | ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { |
e269fc2d | 440 | pTable->KeyTable[i].PairwiseKey.bKeyValid = false; |
33d33e42 | 441 | for (u = 0; u < MAX_GROUP_KEY; u++) |
e269fc2d | 442 | pTable->KeyTable[i].GroupKey[u].bKeyValid = false; |
33d33e42 | 443 | |
92b96797 FB |
444 | pTable->KeyTable[i].dwGTKeyIndex = 0; |
445 | s_vCheckKeyTableValid(pDevice, pTable); | |
4e9b5e2b | 446 | return (true); |
92b96797 FB |
447 | } |
448 | } | |
e269fc2d | 449 | return (false); |
92b96797 FB |
450 | } |
451 | ||
92b96797 FB |
452 | /* |
453 | * Description: Get Transmit Key from table | |
454 | * | |
455 | * Parameters: | |
456 | * In: | |
457 | * pTable - Pointer to Key table | |
458 | * pbyBSSID - BSSID of Key | |
459 | * Out: | |
460 | * pKey - Key return | |
461 | * | |
4e9b5e2b | 462 | * Return Value: true if found otherwise false |
92b96797 FB |
463 | * |
464 | */ | |
da033bfd MP |
465 | int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType, |
466 | PSKeyItem *pKey) | |
92b96797 | 467 | { |
da033bfd MP |
468 | int i, ii; |
469 | ||
470 | *pKey = NULL; | |
92b96797 | 471 | |
fe149785 | 472 | for (i = 0; i < MAX_KEY_TABLE; i++) { |
4e9b5e2b | 473 | if ((pTable->KeyTable[i].bInUse == true) && |
8329419a | 474 | ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { |
92b96797 FB |
475 | |
476 | if (dwKeyType == PAIRWISE_KEY) { | |
477 | ||
4e9b5e2b | 478 | if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) { |
92b96797 FB |
479 | *pKey = &(pTable->KeyTable[i].PairwiseKey); |
480 | ||
481 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:"); | |
482 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PAIRWISE_KEY: KeyTable.abyBSSID: "); | |
483 | for (ii = 0; ii < 6; ii++) { | |
484 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); | |
485 | } | |
486 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
487 | ||
4e9b5e2b | 488 | return (true); |
92b96797 FB |
489 | } |
490 | else { | |
e269fc2d AM |
491 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PairwiseKey.bKeyValid == false\n"); |
492 | return (false); | |
92b96797 FB |
493 | } |
494 | } // End of Type == PAIRWISE | |
495 | else { | |
496 | if (pTable->KeyTable[i].dwGTKeyIndex == 0) { | |
497 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: dwGTKeyIndex == 0 !!!\n"); | |
e269fc2d | 498 | return false; |
92b96797 | 499 | } |
4e9b5e2b | 500 | if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == true) { |
92b96797 FB |
501 | *pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]); |
502 | ||
503 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:"); | |
504 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GROUP_KEY: KeyTable.abyBSSID\n"); | |
505 | for (ii = 0; ii < 6; ii++) { | |
506 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); | |
507 | } | |
508 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
b4dc03af MP |
509 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", |
510 | pTable->KeyTable[i].dwGTKeyIndex); | |
92b96797 | 511 | |
4e9b5e2b | 512 | return (true); |
92b96797 FB |
513 | } |
514 | else { | |
e269fc2d AM |
515 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GroupKey.bKeyValid == false\n"); |
516 | return (false); | |
92b96797 FB |
517 | } |
518 | } // End of Type = GROUP | |
519 | } // BSSID match | |
520 | } | |
521 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: NO Match BSSID !!! "); | |
522 | for (ii = 0; ii < 6; ii++) { | |
523 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(pbyBSSID+ii)); | |
524 | } | |
525 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
e269fc2d | 526 | return (false); |
92b96797 FB |
527 | } |
528 | ||
92b96797 FB |
529 | /* |
530 | * Description: Set Key to table | |
531 | * | |
532 | * Parameters: | |
533 | * In: | |
534 | * pTable - Pointer to Key table | |
535 | * dwKeyIndex - Key index (reference to NDIS DDK) | |
536 | * uKeyLength - Key length | |
537 | * KeyRSC - Key RSC | |
538 | * pbyKey - Pointer to key | |
539 | * Out: | |
540 | * none | |
541 | * | |
4e9b5e2b | 542 | * Return Value: true if success otherwise false |
92b96797 FB |
543 | * |
544 | */ | |
da033bfd MP |
545 | |
546 | int KeybSetDefaultKey(struct vnt_private *pDevice, PSKeyManagement pTable, | |
547 | u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, | |
548 | u8 byKeyDecMode) | |
92b96797 | 549 | { |
da033bfd MP |
550 | int ii; |
551 | PSKeyItem pKey; | |
552 | u32 uKeyIdx; | |
92b96797 | 553 | |
cc856e61 AM |
554 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetDefaultKey: %1x, %d\n", |
555 | (int) dwKeyIndex, (int) uKeyLength); | |
92b96797 FB |
556 | |
557 | if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key | |
e269fc2d | 558 | return (false); |
92b96797 | 559 | } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) { |
e269fc2d | 560 | return (false); |
92b96797 FB |
561 | } |
562 | ||
4ca5218e DC |
563 | if (uKeyLength > MAX_KEY_LEN) |
564 | return false; | |
565 | ||
4e9b5e2b | 566 | pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = true; |
9a0e756c | 567 | for (ii = 0; ii < ETH_ALEN; ii++) |
92b96797 FB |
568 | pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF; |
569 | ||
570 | // Group key | |
571 | pKey = &(pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF]); | |
572 | if ((dwKeyIndex & TRANSMIT_KEY) != 0) { | |
573 | // Group transmit key | |
574 | pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; | |
b4dc03af MP |
575 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
576 | "Group transmit key(R)[%X]: %d\n", | |
577 | pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, | |
578 | MAX_KEY_TABLE-1); | |
92b96797 FB |
579 | |
580 | } | |
581 | pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed | |
582 | pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4); | |
583 | pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode); | |
584 | pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044; // use group key for all address | |
585 | uKeyIdx = (dwKeyIndex & 0x000000FF); | |
586 | ||
587 | if ((uKeyLength == WLAN_WEP232_KEYLEN) && | |
588 | (byKeyDecMode == KEY_CTL_WEP)) { | |
589 | pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000; // disable on-fly disable address match | |
4e9b5e2b | 590 | pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true; |
92b96797 | 591 | } else { |
e269fc2d | 592 | if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == false) |
92b96797 FB |
593 | pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000; // enable on-fly disable address match |
594 | } | |
595 | ||
4e9b5e2b | 596 | pKey->bKeyValid = true; |
92b96797 FB |
597 | pKey->uKeyLength = uKeyLength; |
598 | pKey->dwKeyIndex = dwKeyIndex; | |
599 | pKey->byCipherSuite = byKeyDecMode; | |
3e362598 | 600 | memcpy(pKey->abyKey, pbyKey, uKeyLength); |
92b96797 FB |
601 | if (byKeyDecMode == KEY_CTL_WEP) { |
602 | if (uKeyLength == WLAN_WEP40_KEYLEN) | |
603 | pKey->abyKey[15] &= 0x7F; | |
604 | if (uKeyLength == WLAN_WEP104_KEYLEN) | |
605 | pKey->abyKey[15] |= 0x80; | |
606 | } | |
607 | ||
954e8142 MP |
608 | MACvSetKeyEntry(pDevice, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, |
609 | MAX_KEY_TABLE-1, uKeyIdx, | |
610 | pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, pKey->abyKey); | |
92b96797 | 611 | |
7c65fa2a MP |
612 | if ((dwKeyIndex & USE_KEYRSC) == 0) |
613 | pKey->KeyRSC = 0; /* RSC set by NIC */ | |
614 | else | |
615 | pKey->KeyRSC = *KeyRSC; | |
616 | ||
92b96797 FB |
617 | pKey->dwTSC47_16 = 0; |
618 | pKey->wTSC15_0 = 0; | |
619 | ||
92b96797 FB |
620 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); |
621 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n", pKey->bKeyValid); | |
622 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n", (int)pKey->uKeyLength); | |
623 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: \n"); | |
624 | for (ii = 0; ii < pKey->uKeyLength; ii++) { | |
625 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x", pKey->abyKey[ii]); | |
626 | } | |
627 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
628 | ||
b4dc03af MP |
629 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", |
630 | pKey->dwTSC47_16); | |
92b96797 | 631 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); |
b4dc03af MP |
632 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", |
633 | pKey->dwKeyIndex); | |
92b96797 | 634 | |
4e9b5e2b | 635 | return (true); |
92b96797 FB |
636 | } |
637 | ||
92b96797 FB |
638 | /* |
639 | * Description: Set Key to table | |
640 | * | |
641 | * Parameters: | |
642 | * In: | |
643 | * pTable - Pointer to Key table | |
644 | * dwKeyIndex - Key index (reference to NDIS DDK) | |
645 | * uKeyLength - Key length | |
646 | * KeyRSC - Key RSC | |
647 | * pbyKey - Pointer to key | |
648 | * Out: | |
649 | * none | |
650 | * | |
4e9b5e2b | 651 | * Return Value: true if success otherwise false |
92b96797 FB |
652 | * |
653 | */ | |
da033bfd MP |
654 | |
655 | int KeybSetAllGroupKey(struct vnt_private *pDevice, PSKeyManagement pTable, | |
656 | u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, | |
657 | u8 byKeyDecMode) | |
92b96797 | 658 | { |
da033bfd MP |
659 | int i, ii; |
660 | PSKeyItem pKey; | |
661 | u32 uKeyIdx; | |
92b96797 | 662 | |
b4dc03af MP |
663 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", |
664 | dwKeyIndex); | |
92b96797 | 665 | |
92b96797 | 666 | if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key |
e269fc2d | 667 | return (false); |
92b96797 | 668 | } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) { |
e269fc2d | 669 | return (false); |
92b96797 FB |
670 | } |
671 | ||
672 | for (i=0; i < MAX_KEY_TABLE-1; i++) { | |
4e9b5e2b | 673 | if (pTable->KeyTable[i].bInUse == true) { |
92b96797 FB |
674 | // found table already exist |
675 | // Group key | |
676 | pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); | |
677 | if ((dwKeyIndex & TRANSMIT_KEY) != 0) { | |
678 | // Group transmit key | |
679 | pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; | |
b4dc03af MP |
680 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
681 | "Group transmit key(R)[%X]: %d\n", | |
682 | pTable->KeyTable[i].dwGTKeyIndex, i); | |
92b96797 FB |
683 | |
684 | } | |
685 | pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed | |
686 | pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); | |
687 | pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address | |
688 | uKeyIdx = (dwKeyIndex & 0x000000FF); | |
689 | ||
690 | pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly | |
691 | ||
4e9b5e2b | 692 | pKey->bKeyValid = true; |
92b96797 FB |
693 | pKey->uKeyLength = uKeyLength; |
694 | pKey->dwKeyIndex = dwKeyIndex; | |
695 | pKey->byCipherSuite = byKeyDecMode; | |
3e362598 | 696 | memcpy(pKey->abyKey, pbyKey, uKeyLength); |
92b96797 FB |
697 | if (byKeyDecMode == KEY_CTL_WEP) { |
698 | if (uKeyLength == WLAN_WEP40_KEYLEN) | |
699 | pKey->abyKey[15] &= 0x7F; | |
700 | if (uKeyLength == WLAN_WEP104_KEYLEN) | |
701 | pKey->abyKey[15] |= 0x80; | |
702 | } | |
703 | ||
954e8142 MP |
704 | MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, |
705 | pTable->KeyTable[i].abyBSSID, pKey->abyKey); | |
92b96797 | 706 | |
7c65fa2a MP |
707 | if ((dwKeyIndex & USE_KEYRSC) == 0) |
708 | pKey->KeyRSC = 0; /* RSC set by NIC */ | |
709 | else | |
710 | pKey->KeyRSC = *KeyRSC; | |
711 | ||
92b96797 FB |
712 | pKey->dwTSC47_16 = 0; |
713 | pKey->wTSC15_0 = 0; | |
714 | ||
715 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); | |
716 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); | |
717 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength); | |
718 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); | |
719 | for (ii = 0; ii < pKey->uKeyLength; ii++) { | |
720 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", pKey->abyKey[ii]); | |
721 | } | |
722 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); | |
723 | ||
724 | //DBG_PRN_GRP12(("pKey->dwTSC47_16: %lX\n ", pKey->dwTSC47_16)); | |
725 | //DBG_PRN_GRP12(("pKey->wTSC15_0: %X\n ", pKey->wTSC15_0)); | |
726 | //DBG_PRN_GRP12(("pKey->dwKeyIndex: %lX\n ", pKey->dwKeyIndex)); | |
727 | ||
4e9b5e2b | 728 | } // (pTable->KeyTable[i].bInUse == true) |
92b96797 | 729 | } |
4e9b5e2b | 730 | return (true); |
92b96797 | 731 | } |