Merge branch 'smack-for-3.16' of git://git.gitorious.org/smack-next/kernel into next
[deliverable/linux.git] / drivers / staging / vt6656 / wpactl.c
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
34 #include "wpactl.h"
35 #include "key.h"
36 #include "mac.h"
37 #include "device.h"
38 #include "wmgr.h"
39 #include "iocmd.h"
40 #include "iowpa.h"
41 #include "control.h"
42 #include "rndis.h"
43 #include "rf.h"
44
45 static int msglevel = MSG_LEVEL_INFO;
46
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 */
60 int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
61 {
62 struct viawget_wpa_param *param = ctx;
63 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
64 u32 dwKeyIndex = 0;
65 u8 abyKey[MAX_KEY_LEN];
66 u8 abySeq[MAX_KEY_LEN];
67 u64 KeyRSC;
68 u8 byKeyDecMode = KEY_CTL_WEP;
69 int ret = 0;
70 int uu;
71 int ii;
72
73 if (param->u.wpa_key.alg_name > WPA_ALG_CCMP)
74 return -EINVAL;
75
76 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n",
77 param->u.wpa_key.alg_name);
78 if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
79 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
80 pDevice->bEncryptionEnable = false;
81 pDevice->byKeyIndex = 0;
82 pDevice->bTransmitKey = false;
83 for (uu=0; uu<MAX_KEY_TABLE; uu++) {
84 MACvDisableKeyEntry(pDevice, uu);
85 }
86 return ret;
87 }
88
89 if (param->u.wpa_key.key_len > sizeof(abyKey))
90 return -EINVAL;
91
92 memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
93
94 dwKeyIndex = (u32)(param->u.wpa_key.key_index);
95
96 if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
97 if (dwKeyIndex > 3) {
98 return -EINVAL;
99 } else {
100 if (param->u.wpa_key.set_tx) {
101 pDevice->byKeyIndex = (u8)dwKeyIndex;
102 pDevice->bTransmitKey = true;
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;
116 pDevice->bEncryptionEnable = true;
117 return ret;
118 }
119
120 if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
121 return -EINVAL;
122
123 memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
124
125 if (param->u.wpa_key.seq_len > 0) {
126 for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
127 if (ii < 4)
128 KeyRSC |= (abySeq[ii] << (ii * 8));
129 else
130 KeyRSC |= (abySeq[ii] << ((ii-4) * 8));
131 }
132 dwKeyIndex |= 1 << 29;
133 }
134
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 }
139
140 if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
141 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
142 }
143
144 if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
145 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
146 }
147
148 if (param->u.wpa_key.set_tx)
149 dwKeyIndex |= (1 << 31);
150
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 }
172
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
177 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n");
178 return -EINVAL;
179 }
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 }
187
188 if (is_broadcast_ether_addr(&param->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,
194 &KeyRSC,
195 (u8 *)abyKey,
196 byKeyDecMode
197 ) == true) &&
198 (KeybSetDefaultKey(pDevice,
199 &(pDevice->sKey),
200 dwKeyIndex,
201 param->u.wpa_key.key_len,
202 &KeyRSC,
203 (u8 *)abyKey,
204 byKeyDecMode
205 ) == true) ) {
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), &param->addr[0],
224 dwKeyIndex, param->u.wpa_key.key_len,
225 &KeyRSC, (u8 *)abyKey, byKeyDecMode
226 ) == true) {
227 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
228 } else {
229 // Key Table Full
230 if (ether_addr_equal(param->addr, pDevice->abyBSSID)) {
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)) {
241 pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index;
242 pDevice->bTransmitKey = true;
243 }
244 pDevice->bEncryptionEnable = true;
245
246 return ret;
247 }
248
This page took 0.037958 seconds and 6 git commands to generate.