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