aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211_ioctl.c')
-rw-r--r--net/mac80211/ieee80211_ioctl.c177
1 files changed, 14 insertions, 163 deletions
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index dc05bc66fbb8..8296e7de12c7 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -25,28 +25,6 @@
25#include "ieee80211_rate.h" 25#include "ieee80211_rate.h"
26#include "wpa.h" 26#include "wpa.h"
27#include "aes_ccm.h" 27#include "aes_ccm.h"
28#include "debugfs_key.h"
29
30static void ieee80211_set_hw_encryption(struct net_device *dev,
31 struct sta_info *sta, u8 addr[ETH_ALEN],
32 struct ieee80211_key *key)
33{
34 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
35
36 /* default to sw encryption; this will be cleared by low-level
37 * driver if the hw supports requested encryption */
38 if (key)
39 key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
40
41 if (key && local->ops->set_key) {
42 if (local->ops->set_key(local_to_hw(local), SET_KEY, addr,
43 &key->conf)) {
44 key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
45 key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
46 }
47 }
48}
49
50 28
51static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, 29static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
52 int idx, int alg, int set_tx_key, 30 int idx, int alg, int set_tx_key,
@@ -55,8 +33,7 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
55 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 33 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
56 int ret = 0; 34 int ret = 0;
57 struct sta_info *sta; 35 struct sta_info *sta;
58 struct ieee80211_key *key, *old_key; 36 struct ieee80211_key *key;
59 int try_hwaccel = 1;
60 struct ieee80211_sub_if_data *sdata; 37 struct ieee80211_sub_if_data *sdata;
61 38
62 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 39 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -69,16 +46,6 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
69 return -EINVAL; 46 return -EINVAL;
70 } 47 }
71 key = sdata->keys[idx]; 48 key = sdata->keys[idx];
72
73 /* TODO: consider adding hwaccel support for these; at least
74 * Atheros key cache should be able to handle this since AP is
75 * only transmitting frames with default keys. */
76 /* FIX: hw key cache can be used when only one virtual
77 * STA is associated with each AP. If more than one STA
78 * is associated to the same AP, software encryption
79 * must be used. This should be done automatically
80 * based on configured station devices. For the time
81 * being, this can be only set at compile time. */
82 } else { 49 } else {
83 set_tx_key = 0; 50 set_tx_key = 0;
84 if (idx != 0) { 51 if (idx != 0) {
@@ -101,139 +68,28 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
101 key = sta->key; 68 key = sta->key;
102 } 69 }
103 70
104 /* FIX:
105 * Cannot configure default hwaccel keys with WEP algorithm, if
106 * any of the virtual interfaces is using static WEP
107 * configuration because hwaccel would otherwise try to decrypt
108 * these frames.
109 *
110 * For now, just disable WEP hwaccel for broadcast when there is
111 * possibility of conflict with default keys. This can maybe later be
112 * optimized by using non-default keys (at least with Atheros ar521x).
113 */
114 if (!sta && alg == ALG_WEP &&
115 sdata->type != IEEE80211_IF_TYPE_IBSS &&
116 sdata->type != IEEE80211_IF_TYPE_AP) {
117 try_hwaccel = 0;
118 }
119
120 if (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) {
121 /* Software encryption cannot be used with devices that hide
122 * encryption from the host system, so always try to use
123 * hardware acceleration with such devices. */
124 try_hwaccel = 1;
125 }
126
127 if ((local->hw.flags & IEEE80211_HW_NO_TKIP_WMM_HWACCEL) &&
128 alg == ALG_TKIP) {
129 if (sta && (sta->flags & WLAN_STA_WME)) {
130 /* Hardware does not support hwaccel with TKIP when using WMM.
131 */
132 try_hwaccel = 0;
133 }
134 else if (sdata->type == IEEE80211_IF_TYPE_STA) {
135 sta = sta_info_get(local, sdata->u.sta.bssid);
136 if (sta) {
137 if (sta->flags & WLAN_STA_WME) {
138 try_hwaccel = 0;
139 }
140 sta_info_put(sta);
141 sta = NULL;
142 }
143 }
144 }
145
146 if (alg == ALG_NONE) { 71 if (alg == ALG_NONE) {
147 if (try_hwaccel && key &&
148 key->conf.hw_key_idx != HW_KEY_IDX_INVALID &&
149 local->ops->set_key &&
150 local->ops->set_key(local_to_hw(local), DISABLE_KEY,
151 sta_addr, &key->conf)) {
152 printk(KERN_DEBUG "%s: set_encrypt - low-level disable"
153 " failed\n", dev->name);
154 ret = -EINVAL;
155 }
156
157 if (set_tx_key || sdata->default_key == key) {
158 ieee80211_debugfs_key_remove_default(sdata);
159 sdata->default_key = NULL;
160 }
161 ieee80211_debugfs_key_remove(key);
162 if (sta)
163 sta->key = NULL;
164 else
165 sdata->keys[idx] = NULL;
166 ieee80211_key_free(key); 72 ieee80211_key_free(key);
167 key = NULL; 73 key = NULL;
168 } else { 74 } else {
169 old_key = key; 75 /*
170 key = ieee80211_key_alloc(sta ? NULL : sdata, idx, key_len, 76 * Need to free it before allocating a new one with
171 GFP_KERNEL); 77 * with the same index or the ordering to the driver's
78 * set_key() callback becomes confused.
79 */
80 ieee80211_key_free(key);
81 key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
172 if (!key) { 82 if (!key) {
173 ret = -ENOMEM; 83 ret = -ENOMEM;
174 goto err_out; 84 goto err_out;
175 } 85 }
176
177 /* default to sw encryption; low-level driver sets these if the
178 * requested encryption is supported */
179 key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
180 key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
181
182 key->conf.alg = alg;
183 key->conf.keyidx = idx;
184 key->conf.keylen = key_len;
185 memcpy(key->conf.key, _key, key_len);
186
187 if (alg == ALG_CCMP) {
188 /* Initialize AES key state here as an optimization
189 * so that it does not need to be initialized for every
190 * packet. */
191 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
192 key->conf.key);
193 if (!key->u.ccmp.tfm) {
194 ret = -ENOMEM;
195 goto err_free;
196 }
197 }
198
199 if (set_tx_key || sdata->default_key == old_key) {
200 ieee80211_debugfs_key_remove_default(sdata);
201 sdata->default_key = NULL;
202 }
203 ieee80211_debugfs_key_remove(old_key);
204 if (sta)
205 sta->key = key;
206 else
207 sdata->keys[idx] = key;
208 ieee80211_key_free(old_key);
209 ieee80211_debugfs_key_add(local, key);
210 if (sta)
211 ieee80211_debugfs_key_sta_link(key, sta);
212
213 if (try_hwaccel &&
214 (alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP))
215 ieee80211_set_hw_encryption(dev, sta, sta_addr, key);
216 }
217
218 if (set_tx_key || (!sta && !sdata->default_key && key)) {
219 sdata->default_key = key;
220 if (key)
221 ieee80211_debugfs_key_add_default(sdata);
222
223 if (local->ops->set_key_idx &&
224 local->ops->set_key_idx(local_to_hw(local), idx))
225 printk(KERN_DEBUG "%s: failed to set TX key idx for "
226 "low-level driver\n", dev->name);
227 } 86 }
228 87
229 if (sta) 88 if (set_tx_key || (!sta && !sdata->default_key && key))
230 sta_info_put(sta); 89 ieee80211_set_default_key(sdata, idx);
231 90
232 return 0; 91 ret = 0;
233 92 err_out:
234err_free:
235 ieee80211_key_free(key);
236err_out:
237 if (sta) 93 if (sta)
238 sta_info_put(sta); 94 sta_info_put(sta);
239 return ret; 95 return ret;
@@ -1181,12 +1037,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev,
1181 alg = ALG_NONE; 1037 alg = ALG_NONE;
1182 else if (erq->length == 0) { 1038 else if (erq->length == 0) {
1183 /* No key data - just set the default TX key index */ 1039 /* No key data - just set the default TX key index */
1184 if (sdata->default_key != sdata->keys[idx]) { 1040 ieee80211_set_default_key(sdata, idx);
1185 ieee80211_debugfs_key_remove_default(sdata);
1186 sdata->default_key = sdata->keys[idx];
1187 if (sdata->default_key)
1188 ieee80211_debugfs_key_add_default(sdata);
1189 }
1190 return 0; 1041 return 0;
1191 } 1042 }
1192 1043
@@ -1232,7 +1083,7 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev,
1232 } 1083 }
1233 1084
1234 memcpy(key, sdata->keys[idx]->conf.key, 1085 memcpy(key, sdata->keys[idx]->conf.key,
1235 min((int)erq->length, sdata->keys[idx]->conf.keylen)); 1086 min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
1236 erq->length = sdata->keys[idx]->conf.keylen; 1087 erq->length = sdata->keys[idx]->conf.keylen;
1237 erq->flags |= IW_ENCODE_ENABLED; 1088 erq->flags |= IW_ENCODE_ENABLED;
1238 1089