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: wpactl.c | |
21 | * | |
22 | * Purpose: handle wpa supplicant ioctl input/out functions | |
23 | * | |
24 | * Author: Lyndon Chen | |
25 | * | |
26 | * Date: July 28, 2006 | |
27 | * | |
28 | * Functions: | |
29 | * | |
30 | * Revision History: | |
31 | * | |
32 | */ | |
33 | ||
92b96797 | 34 | #include "wpactl.h" |
92b96797 | 35 | #include "key.h" |
92b96797 | 36 | #include "mac.h" |
92b96797 | 37 | #include "device.h" |
92b96797 | 38 | #include "wmgr.h" |
92b96797 | 39 | #include "iocmd.h" |
92b96797 | 40 | #include "iowpa.h" |
62c8526d | 41 | #include "usbpipe.h" |
92b96797 | 42 | #include "rf.h" |
92b96797 | 43 | |
4e1efd6e | 44 | static int msglevel = MSG_LEVEL_INFO; |
92b96797 | 45 | |
92b96797 FB |
46 | /* |
47 | * Description: | |
48 | * Set WPA algorithm & keys | |
49 | * | |
50 | * Parameters: | |
51 | * In: | |
52 | * pDevice - | |
53 | * param - | |
54 | * Out: | |
55 | * | |
56 | * Return Value: | |
57 | * | |
58 | */ | |
fe5d00eb | 59 | int wpa_set_keys(struct vnt_private *pDevice, void *ctx) |
92b96797 | 60 | { |
4e1efd6e | 61 | struct viawget_wpa_param *param = ctx; |
fe5d00eb | 62 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; |
52a7e64b | 63 | u32 dwKeyIndex = 0; |
b902fbfe AM |
64 | u8 abyKey[MAX_KEY_LEN]; |
65 | u8 abySeq[MAX_KEY_LEN]; | |
7c65fa2a | 66 | u64 KeyRSC; |
b902fbfe | 67 | u8 byKeyDecMode = KEY_CTL_WEP; |
92b96797 | 68 | int ret = 0; |
9190c4d2 | 69 | u8 uu; |
4e1efd6e | 70 | int ii; |
92b96797 FB |
71 | |
72 | if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) | |
73 | return -EINVAL; | |
74 | ||
4e1efd6e JJ |
75 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", |
76 | param->u.wpa_key.alg_name); | |
92b96797 | 77 | if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { |
4e1efd6e | 78 | pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; |
e269fc2d | 79 | pDevice->bEncryptionEnable = false; |
4e1efd6e | 80 | pDevice->byKeyIndex = 0; |
e269fc2d | 81 | pDevice->bTransmitKey = false; |
4e1efd6e JJ |
82 | for (uu=0; uu<MAX_KEY_TABLE; uu++) { |
83 | MACvDisableKeyEntry(pDevice, uu); | |
84 | } | |
85 | return ret; | |
86 | } | |
92b96797 | 87 | |
3b371fe4 | 88 | if (param->u.wpa_key.key_len > sizeof(abyKey)) |
657d1b0d DC |
89 | return -EINVAL; |
90 | ||
c9f3bc59 | 91 | memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); |
92b96797 | 92 | |
52a7e64b | 93 | dwKeyIndex = (u32)(param->u.wpa_key.key_index); |
92b96797 FB |
94 | |
95 | if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { | |
4e1efd6e JJ |
96 | if (dwKeyIndex > 3) { |
97 | return -EINVAL; | |
98 | } else { | |
99 | if (param->u.wpa_key.set_tx) { | |
b902fbfe | 100 | pDevice->byKeyIndex = (u8)dwKeyIndex; |
4e9b5e2b | 101 | pDevice->bTransmitKey = true; |
4e1efd6e JJ |
102 | dwKeyIndex |= (1 << 31); |
103 | } | |
104 | KeybSetDefaultKey( pDevice, | |
105 | &(pDevice->sKey), | |
106 | dwKeyIndex & ~(BIT30 | USE_KEYRSC), | |
107 | param->u.wpa_key.key_len, | |
108 | NULL, | |
109 | abyKey, | |
110 | KEY_CTL_WEP | |
111 | ); | |
112 | ||
113 | } | |
114 | pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; | |
4e9b5e2b | 115 | pDevice->bEncryptionEnable = true; |
4e1efd6e | 116 | return ret; |
92b96797 FB |
117 | } |
118 | ||
657d1b0d DC |
119 | if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq)) |
120 | return -EINVAL; | |
121 | ||
c9f3bc59 | 122 | memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); |
92b96797 FB |
123 | |
124 | if (param->u.wpa_key.seq_len > 0) { | |
125 | for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { | |
4e1efd6e | 126 | if (ii < 4) |
7c65fa2a | 127 | KeyRSC |= (abySeq[ii] << (ii * 8)); |
4e1efd6e | 128 | else |
7c65fa2a | 129 | KeyRSC |= (abySeq[ii] << ((ii-4) * 8)); |
92b96797 FB |
130 | } |
131 | dwKeyIndex |= 1 << 29; | |
132 | } | |
133 | ||
4e1efd6e JJ |
134 | if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { |
135 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); | |
136 | return -EINVAL; | |
137 | } | |
92b96797 FB |
138 | |
139 | if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) { | |
4e1efd6e JJ |
140 | pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; |
141 | } | |
92b96797 FB |
142 | |
143 | if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) { | |
4e1efd6e JJ |
144 | pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; |
145 | } | |
92b96797 FB |
146 | |
147 | if (param->u.wpa_key.set_tx) | |
148 | dwKeyIndex |= (1 << 31); | |
149 | ||
4e1efd6e JJ |
150 | if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) |
151 | byKeyDecMode = KEY_CTL_CCMP; | |
152 | else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) | |
153 | byKeyDecMode = KEY_CTL_TKIP; | |
154 | else | |
155 | byKeyDecMode = KEY_CTL_WEP; | |
156 | ||
157 | // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled | |
158 | if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { | |
159 | if (param->u.wpa_key.key_len == MAX_KEY_LEN) | |
160 | byKeyDecMode = KEY_CTL_TKIP; | |
161 | else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) | |
162 | byKeyDecMode = KEY_CTL_WEP; | |
163 | else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) | |
164 | byKeyDecMode = KEY_CTL_WEP; | |
165 | } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { | |
166 | if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) | |
167 | byKeyDecMode = KEY_CTL_WEP; | |
168 | else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) | |
169 | byKeyDecMode = KEY_CTL_WEP; | |
170 | } | |
92b96797 | 171 | |
4e1efd6e JJ |
172 | // Check TKIP key length |
173 | if ((byKeyDecMode == KEY_CTL_TKIP) && | |
174 | (param->u.wpa_key.key_len != MAX_KEY_LEN)) { | |
175 | // TKIP Key must be 256 bits | |
a0a1f61a | 176 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n"); |
4e1efd6e | 177 | return -EINVAL; |
92b96797 | 178 | } |
4e1efd6e JJ |
179 | // Check AES key length |
180 | if ((byKeyDecMode == KEY_CTL_CCMP) && | |
181 | (param->u.wpa_key.key_len != AES_KEY_LEN)) { | |
182 | // AES Key must be 128 bits | |
183 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n"); | |
184 | return -EINVAL; | |
185 | } | |
92b96797 | 186 | |
4e1efd6e JJ |
187 | if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { |
188 | /* if broadcast, set the key as every key entry's group key */ | |
189 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); | |
190 | ||
191 | if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex, | |
192 | param->u.wpa_key.key_len, | |
7c65fa2a | 193 | &KeyRSC, |
b902fbfe | 194 | (u8 *)abyKey, |
4e1efd6e | 195 | byKeyDecMode |
4e9b5e2b | 196 | ) == true) && |
4e1efd6e JJ |
197 | (KeybSetDefaultKey(pDevice, |
198 | &(pDevice->sKey), | |
199 | dwKeyIndex, | |
200 | param->u.wpa_key.key_len, | |
7c65fa2a | 201 | &KeyRSC, |
b902fbfe | 202 | (u8 *)abyKey, |
4e1efd6e | 203 | byKeyDecMode |
4e9b5e2b | 204 | ) == true) ) { |
4e1efd6e JJ |
205 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); |
206 | } else { | |
207 | return -EINVAL; | |
208 | } | |
209 | } else { | |
210 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); | |
211 | // BSSID not 0xffffffffffff | |
212 | // Pairwise Key can't be WEP | |
213 | if (byKeyDecMode == KEY_CTL_WEP) { | |
214 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); | |
215 | return -EINVAL; | |
216 | } | |
217 | dwKeyIndex |= (1 << 30); // set pairwise key | |
218 | if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { | |
219 | //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); | |
220 | return -EINVAL; | |
221 | } | |
222 | if (KeybSetKey(pDevice, &(pDevice->sKey), ¶m->addr[0], | |
223 | dwKeyIndex, param->u.wpa_key.key_len, | |
b902fbfe | 224 | &KeyRSC, (u8 *)abyKey, byKeyDecMode |
4e9b5e2b | 225 | ) == true) { |
4e1efd6e JJ |
226 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); |
227 | } else { | |
228 | // Key Table Full | |
8329419a | 229 | if (ether_addr_equal(param->addr, pDevice->abyBSSID)) { |
4e1efd6e JJ |
230 | //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); |
231 | return -EINVAL; | |
232 | } else { | |
233 | // Save Key and configure just before associate/reassociate to BSSID | |
234 | // we do not implement now | |
235 | return -EINVAL; | |
236 | } | |
237 | } | |
238 | } // BSSID not 0xffffffffffff | |
239 | if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { | |
b902fbfe | 240 | pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index; |
4e9b5e2b | 241 | pDevice->bTransmitKey = true; |
4e1efd6e | 242 | } |
4e9b5e2b | 243 | pDevice->bEncryptionEnable = true; |
92b96797 FB |
244 | |
245 | return ret; | |
92b96797 FB |
246 | } |
247 |