]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/vt6656/wpactl.c
Merge tag 'for-linus-3.11-merge-window-part-2' of git://git.kernel.org/pub/scm/linux...
[karo-tx-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 && 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 (!compare_ether_addr(&param->addr[0], 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