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