Merge tag 'iio-for-3.16c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
[cascardo/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 "rf.h"
43
44 static int msglevel = MSG_LEVEL_INFO;
45
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  */
59 int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
60 {
61         struct viawget_wpa_param *param = ctx;
62         struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
63         u32 dwKeyIndex = 0;
64         u8 abyKey[MAX_KEY_LEN];
65         u8 abySeq[MAX_KEY_LEN];
66         u64 KeyRSC;
67         u8 byKeyDecMode = KEY_CTL_WEP;
68         int ret = 0;
69         u8 uu;
70         int ii;
71
72         if (param->u.wpa_key.alg_name > WPA_ALG_CCMP)
73                 return -EINVAL;
74
75         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n",
76                 param->u.wpa_key.alg_name);
77         if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
78                 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
79                 pDevice->bEncryptionEnable = false;
80                 pDevice->byKeyIndex = 0;
81                 pDevice->bTransmitKey = false;
82                 for (uu=0; uu<MAX_KEY_TABLE; uu++) {
83                         MACvDisableKeyEntry(pDevice, uu);
84                 }
85                 return ret;
86         }
87
88         if (param->u.wpa_key.key_len > sizeof(abyKey))
89                 return -EINVAL;
90
91         memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
92
93         dwKeyIndex = (u32)(param->u.wpa_key.key_index);
94
95         if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
96                 if (dwKeyIndex > 3) {
97                         return -EINVAL;
98                 } else {
99                         if (param->u.wpa_key.set_tx) {
100                                 pDevice->byKeyIndex = (u8)dwKeyIndex;
101                                 pDevice->bTransmitKey = true;
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;
115                 pDevice->bEncryptionEnable = true;
116                 return ret;
117         }
118
119         if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
120                 return -EINVAL;
121
122         memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
123
124         if (param->u.wpa_key.seq_len > 0) {
125                 for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
126                         if (ii < 4)
127                                 KeyRSC |= (abySeq[ii] << (ii * 8));
128                         else
129                                 KeyRSC |= (abySeq[ii] << ((ii-4) * 8));
130                 }
131                 dwKeyIndex |= 1 << 29;
132         }
133
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         }
138
139         if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
140                 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
141         }
142
143         if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
144                 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
145         }
146
147         if (param->u.wpa_key.set_tx)
148                 dwKeyIndex |= (1 << 31);
149
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         }
171
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
176                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n");
177                 return -EINVAL;
178     }
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         }
186
187         if (is_broadcast_ether_addr(&param->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,
193                                                         &KeyRSC,
194                                                         (u8 *)abyKey,
195                                                         byKeyDecMode
196                                         ) == true) &&
197                         (KeybSetDefaultKey(pDevice,
198                                         &(pDevice->sKey),
199                                         dwKeyIndex,
200                                         param->u.wpa_key.key_len,
201                                         &KeyRSC,
202                                         (u8 *)abyKey,
203                                         byKeyDecMode
204                                 ) == true) ) {
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), &param->addr[0],
223                                 dwKeyIndex, param->u.wpa_key.key_len,
224                                 &KeyRSC, (u8 *)abyKey, byKeyDecMode
225                                 ) == true) {
226                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
227                 } else {
228                         // Key Table Full
229                         if (ether_addr_equal(param->addr, pDevice->abyBSSID)) {
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)) {
240                 pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index;
241                 pDevice->bTransmitKey = true;
242         }
243         pDevice->bEncryptionEnable = true;
244
245         return ret;
246 }
247