aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-08-28 17:01:55 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:48:53 -0400
commit11a843b7e16062389c53ba393c7913956e034eb2 (patch)
tree7f557a55220a0de38f0eafe1a5147487ec39b790 /net/mac80211
parent3aefaa3294193c931b20a574f718efee6baf27d4 (diff)
[MAC80211]: rework key handling
This moves all the key handling code out from ieee80211_ioctl.c into key.c and also does the following changes including documentation updates in mac80211.h: 1) Turn off hardware acceleration for keys when the interface is down. This is necessary because otherwise monitor interfaces could be decrypting frames for other interfaces that are down at the moment. Also, it should go some way towards better suspend/resume support, in any case the routines used here could be used for that as well. Additionally, this makes the driver interface nicer, keys for a specific local MAC address are only ever present while an interface with that MAC address is enabled. 2) Change driver set_key() callback interface to allow only return values of -ENOSPC, -EOPNOTSUPP and 0, warn on all other return values. This allows debugging the stack when a driver notices it's handed a key while it is down. 3) Invert the flag meaning to KEY_FLAG_UPLOADED_TO_HARDWARE. 4) Remove REMOVE_ALL_KEYS command as it isn't used nor do we want to use it, we'll use DISABLE_KEY for each key. It is hard to use REMOVE_ALL_KEYS because we can handle multiple virtual interfaces with different key configuration, so we'd have to keep track of a lot of state for this and that isn't worth it. 5) Warn when disabling a key fails, it musn't. 6) Remove IEEE80211_HW_NO_TKIP_WMM_HWACCEL in favour of per-key IEEE80211_KEY_FLAG_WMM_STA to let driver sort it out itself. 7) Tell driver that a (non-WEP) key is used only for transmission by using an all-zeroes station MAC address when configuring. 8) Change the set_key() callback to have access to the local MAC address the key is being added for. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Acked-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/debugfs_key.c4
-rw-r--r--net/mac80211/ieee80211.c6
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/ieee80211_iface.c21
-rw-r--r--net/mac80211/ieee80211_ioctl.c177
-rw-r--r--net/mac80211/ieee80211_key.h26
-rw-r--r--net/mac80211/key.c243
-rw-r--r--net/mac80211/rx.c7
-rw-r--r--net/mac80211/sta_info.c10
-rw-r--r--net/mac80211/tx.c4
-rw-r--r--net/mac80211/wpa.c30
11 files changed, 318 insertions, 218 deletions
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 246938c32d4d..36e7812da556 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -25,6 +25,7 @@ static ssize_t key_##name##_read(struct file *file, \
25 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ 25 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
26} 26}
27#define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n") 27#define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n")
28#define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n")
28 29
29#define KEY_OPS(name) \ 30#define KEY_OPS(name) \
30static const struct file_operations key_ ##name## _ops = { \ 31static const struct file_operations key_ ##name## _ops = { \
@@ -39,7 +40,6 @@ static const struct file_operations key_ ##name## _ops = { \
39#define KEY_CONF_READ(name, buflen, format_string) \ 40#define KEY_CONF_READ(name, buflen, format_string) \
40 KEY_READ(conf_##name, conf.name, buflen, format_string) 41 KEY_READ(conf_##name, conf.name, buflen, format_string)
41#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n") 42#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n")
42#define KEY_CONF_READ_X(name) KEY_CONF_READ(name, 20, "0x%x\n")
43 43
44#define KEY_CONF_OPS(name) \ 44#define KEY_CONF_OPS(name) \
45static const struct file_operations key_ ##name## _ops = { \ 45static const struct file_operations key_ ##name## _ops = { \
@@ -54,7 +54,7 @@ static const struct file_operations key_ ##name## _ops = { \
54KEY_CONF_FILE(keylen, D); 54KEY_CONF_FILE(keylen, D);
55KEY_CONF_FILE(keyidx, D); 55KEY_CONF_FILE(keyidx, D);
56KEY_CONF_FILE(hw_key_idx, D); 56KEY_CONF_FILE(hw_key_idx, D);
57KEY_CONF_FILE(flags, X); 57KEY_FILE(flags, X);
58KEY_FILE(tx_rx_count, D); 58KEY_FILE(tx_rx_count, D);
59 59
60static ssize_t key_algorithm_read(struct file *file, 60static ssize_t key_algorithm_read(struct file *file,
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 5d5034f36fde..73e314e33de2 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -442,6 +442,7 @@ static int ieee80211_open(struct net_device *dev)
442 } else { 442 } else {
443 ieee80211_if_config(dev); 443 ieee80211_if_config(dev);
444 ieee80211_reset_erp_info(dev); 444 ieee80211_reset_erp_info(dev);
445 ieee80211_enable_keys(sdata);
445 } 446 }
446 447
447 if (sdata->type == IEEE80211_IF_TYPE_STA && 448 if (sdata->type == IEEE80211_IF_TYPE_STA &&
@@ -510,6 +511,9 @@ static int ieee80211_stop(struct net_device *dev)
510 local->monitors--; 511 local->monitors--;
511 if (!local->monitors) 512 if (!local->monitors)
512 local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; 513 local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
514 } else {
515 /* disable all keys for as long as this netdev is down */
516 ieee80211_disable_keys(sdata);
513 } 517 }
514 518
515 local->open_count--; 519 local->open_count--;
@@ -908,7 +912,7 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
908 } 912 }
909 913
910 if (skb->len >= mic_len && 914 if (skb->len >= mic_len &&
911 (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) 915 !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
912 skb_trim(skb, skb->len - mic_len); 916 skb_trim(skb, skb->len - mic_len);
913 if (skb->len >= iv_len && skb->len > hdrlen) { 917 if (skb->len >= iv_len && skb->len > hdrlen) {
914 memmove(skb->data + iv_len, skb->data, hdrlen); 918 memmove(skb->data + iv_len, skb->data, hdrlen);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 7b5cc146c81b..0149f9055918 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -291,6 +291,9 @@ struct ieee80211_sub_if_data {
291 291
292 struct wireless_dev wdev; 292 struct wireless_dev wdev;
293 293
294 /* keys */
295 struct list_head key_list;
296
294 struct net_device *dev; 297 struct net_device *dev;
295 struct ieee80211_local *local; 298 struct ieee80211_local *local;
296 299
@@ -810,11 +813,6 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
810int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); 813int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
811int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); 814int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
812 815
813/* key handling */
814struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
815 int idx, size_t key_len, gfp_t flags);
816void ieee80211_key_free(struct ieee80211_key *key);
817
818/* utility functions/constants */ 816/* utility functions/constants */
819extern void *mac80211_wiphy_privid; /* for wiphy privid */ 817extern void *mac80211_wiphy_privid; /* for wiphy privid */
820extern const unsigned char rfc1042_header[6]; 818extern const unsigned char rfc1042_header[6];
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index 8bb85f194385..f9c74bb09d31 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -25,6 +25,8 @@ void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
25 sdata->eapol = 1; 25 sdata->eapol = 1;
26 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) 26 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
27 skb_queue_head_init(&sdata->fragments[i].skb_list); 27 skb_queue_head_init(&sdata->fragments[i].skb_list);
28
29 INIT_LIST_HEAD(&sdata->key_list);
28} 30}
29 31
30static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) 32static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
@@ -210,25 +212,12 @@ void ieee80211_if_reinit(struct net_device *dev)
210 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 212 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
211 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 213 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
212 struct sta_info *sta; 214 struct sta_info *sta;
213 int i;
214 215
215 ASSERT_RTNL(); 216 ASSERT_RTNL();
217
218 ieee80211_free_keys(sdata);
219
216 ieee80211_if_sdata_deinit(sdata); 220 ieee80211_if_sdata_deinit(sdata);
217 for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
218 if (!sdata->keys[i])
219 continue;
220#if 0
221 /* The interface is down at the moment, so there is not
222 * really much point in disabling the keys at this point. */
223 memset(addr, 0xff, ETH_ALEN);
224 if (local->ops->set_key)
225 local->ops->set_key(local_to_hw(local), DISABLE_KEY, addr,
226 local->keys[i],
227 local->default_wep_only);
228#endif
229 ieee80211_key_free(sdata->keys[i]);
230 sdata->keys[i] = NULL;
231 }
232 221
233 switch (sdata->type) { 222 switch (sdata->type) {
234 case IEEE80211_IF_TYPE_AP: { 223 case IEEE80211_IF_TYPE_AP: {
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
diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
index 58e192530826..a4e5fbbe045c 100644
--- a/net/mac80211/ieee80211_key.h
+++ b/net/mac80211/ieee80211_key.h
@@ -41,7 +41,21 @@
41 41
42#define NUM_RX_DATA_QUEUES 17 42#define NUM_RX_DATA_QUEUES 17
43 43
44struct ieee80211_local;
45struct ieee80211_sub_if_data;
46struct sta_info;
47
48#define KEY_FLAG_UPLOADED_TO_HARDWARE (1<<0)
49
44struct ieee80211_key { 50struct ieee80211_key {
51 struct ieee80211_local *local;
52 struct ieee80211_sub_if_data *sdata;
53 struct sta_info *sta;
54
55 struct list_head list;
56
57 unsigned int flags;
58
45 union { 59 union {
46 struct { 60 struct {
47 /* last used TSC */ 61 /* last used TSC */
@@ -97,4 +111,16 @@ struct ieee80211_key {
97 struct ieee80211_key_conf conf; 111 struct ieee80211_key_conf conf;
98}; 112};
99 113
114struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
115 struct sta_info *sta,
116 ieee80211_key_alg alg,
117 int idx,
118 size_t key_len,
119 const u8 *key_data);
120void ieee80211_key_free(struct ieee80211_key *key);
121void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
122void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
123void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
124void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
125
100#endif /* IEEE80211_KEY_H */ 126#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 843d1577f00f..178f00cf61b9 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -2,25 +2,198 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
9 */ 10 */
10 11
12#include <linux/if_ether.h>
13#include <linux/etherdevice.h>
14#include <linux/list.h>
11#include <net/mac80211.h> 15#include <net/mac80211.h>
12#include "ieee80211_i.h" 16#include "ieee80211_i.h"
13#include "debugfs_key.h" 17#include "debugfs_key.h"
14#include "aes_ccm.h" 18#include "aes_ccm.h"
15 19
20
21/*
22 * Key handling basics
23 *
24 * Key handling in mac80211 is done based on per-interface (sub_if_data)
25 * keys and per-station keys. Since each station belongs to an interface,
26 * each station key also belongs to that interface.
27 *
28 * Hardware acceleration is done on a best-effort basis, for each key
29 * that is eligible the hardware is asked to enable that key but if
30 * it cannot do that they key is simply kept for software encryption.
31 * There is currently no way of knowing this except by looking into
32 * debugfs.
33 *
34 * All operations here are called under RTNL so no extra locking is
35 * required.
36 */
37
38static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
39static const u8 zero_addr[ETH_ALEN];
40
41static const u8 *get_mac_for_key(struct ieee80211_key *key)
42{
43 const u8 *addr = bcast_addr;
44
45 /*
46 * If we're an AP we won't ever receive frames with a non-WEP
47 * group key so we tell the driver that by using the zero MAC
48 * address to indicate a transmit-only key.
49 */
50 if (key->conf.alg != ALG_WEP &&
51 (key->sdata->type == IEEE80211_IF_TYPE_AP ||
52 key->sdata->type == IEEE80211_IF_TYPE_VLAN))
53 addr = zero_addr;
54
55 if (key->sta)
56 addr = key->sta->addr;
57
58 return addr;
59}
60
61static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
62{
63 const u8 *addr;
64 int ret;
65
66 if (!key->local->ops->set_key)
67 return;
68
69 addr = get_mac_for_key(key);
70
71 ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY,
72 key->sdata->dev->dev_addr, addr,
73 &key->conf);
74
75 WARN_ON(!ret && (key->conf.hw_key_idx == HW_KEY_IDX_INVALID));
76
77 if (!ret)
78 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
79
80 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
81 printk(KERN_ERR "mac80211-%s: failed to set key "
82 "(%d, " MAC_FMT ") to hardware (%d)\n",
83 wiphy_name(key->local->hw.wiphy),
84 key->conf.keyidx, MAC_ARG(addr), ret);
85}
86
87static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
88{
89 const u8 *addr;
90 int ret;
91
92 if (!key->local->ops->set_key)
93 return;
94
95 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
96 return;
97
98 addr = get_mac_for_key(key);
99
100 ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY,
101 key->sdata->dev->dev_addr, addr,
102 &key->conf);
103
104 if (ret)
105 printk(KERN_ERR "mac80211-%s: failed to remove key "
106 "(%d, " MAC_FMT ") from hardware (%d)\n",
107 wiphy_name(key->local->hw.wiphy),
108 key->conf.keyidx, MAC_ARG(addr), ret);
109
110 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
111 key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
112}
113
16struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata, 114struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
17 int idx, size_t key_len, gfp_t flags) 115 struct sta_info *sta,
116 ieee80211_key_alg alg,
117 int idx,
118 size_t key_len,
119 const u8 *key_data)
18{ 120{
19 struct ieee80211_key *key; 121 struct ieee80211_key *key;
20 122
21 key = kzalloc(sizeof(struct ieee80211_key) + key_len, flags); 123 BUG_ON(alg == ALG_NONE);
124
125 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
22 if (!key) 126 if (!key)
23 return NULL; 127 return NULL;
128
129 /*
130 * Default to software encryption; we'll later upload the
131 * key to the hardware if possible.
132 */
133 key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
134 key->conf.flags = 0;
135 key->flags = 0;
136
137 key->conf.alg = alg;
138 key->conf.keyidx = idx;
139 key->conf.keylen = key_len;
140 memcpy(key->conf.key, key_data, key_len);
141
142 key->local = sdata->local;
143 key->sdata = sdata;
144 key->sta = sta;
145
146 if (alg == ALG_CCMP) {
147 /*
148 * Initialize AES key state here as an optimization so that
149 * it does not need to be initialized for every packet.
150 */
151 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
152 if (!key->u.ccmp.tfm) {
153 ieee80211_key_free(key);
154 return NULL;
155 }
156 }
157
158 ieee80211_debugfs_key_add(key->local, key);
159
160 if (sta) {
161 ieee80211_debugfs_key_sta_link(key, sta);
162 sta->key = key;
163 /*
164 * some hardware cannot handle TKIP with QoS, so
165 * we indicate whether QoS could be in use.
166 */
167 if (sta->flags & WLAN_STA_WME)
168 key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
169 } else {
170 if (sdata->type == IEEE80211_IF_TYPE_STA) {
171 struct sta_info *ap;
172
173 /* same here, the AP could be using QoS */
174 ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
175 if (ap) {
176 if (ap->flags & WLAN_STA_WME)
177 key->conf.flags |=
178 IEEE80211_KEY_FLAG_WMM_STA;
179 sta_info_put(ap);
180 }
181 }
182
183 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) {
184 if (!sdata->keys[idx])
185 sdata->keys[idx] = key;
186 else
187 WARN_ON(1);
188 } else
189 WARN_ON(1);
190 }
191
192 list_add(&key->list, &sdata->key_list);
193
194 if (netif_running(key->sdata->dev))
195 ieee80211_key_enable_hw_accel(key);
196
24 return key; 197 return key;
25} 198}
26 199
@@ -29,8 +202,74 @@ void ieee80211_key_free(struct ieee80211_key *key)
29 if (!key) 202 if (!key)
30 return; 203 return;
31 204
205 ieee80211_key_disable_hw_accel(key);
206
207 if (key->sta) {
208 key->sta->key = NULL;
209 } else {
210 if (key->sdata->default_key == key)
211 ieee80211_set_default_key(key->sdata, -1);
212 if (key->conf.keyidx >= 0 &&
213 key->conf.keyidx < NUM_DEFAULT_KEYS)
214 key->sdata->keys[key->conf.keyidx] = NULL;
215 else
216 WARN_ON(1);
217 }
218
32 if (key->conf.alg == ALG_CCMP) 219 if (key->conf.alg == ALG_CCMP)
33 ieee80211_aes_key_free(key->u.ccmp.tfm); 220 ieee80211_aes_key_free(key->u.ccmp.tfm);
34 ieee80211_debugfs_key_remove(key); 221 ieee80211_debugfs_key_remove(key);
222
223 list_del(&key->list);
224
35 kfree(key); 225 kfree(key);
36} 226}
227
228void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
229{
230 struct ieee80211_key *key = NULL;
231
232 if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
233 key = sdata->keys[idx];
234
235 if (sdata->default_key != key) {
236 ieee80211_debugfs_key_remove_default(sdata);
237
238 sdata->default_key = key;
239
240 if (sdata->default_key)
241 ieee80211_debugfs_key_add_default(sdata);
242
243 if (sdata->local->ops->set_key_idx)
244 sdata->local->ops->set_key_idx(
245 local_to_hw(sdata->local), idx);
246 }
247}
248
249void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
250{
251 struct ieee80211_key *key, *tmp;
252
253 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
254 ieee80211_key_free(key);
255}
256
257void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
258{
259 struct ieee80211_key *key;
260
261 WARN_ON(!netif_running(sdata->dev));
262 if (!netif_running(sdata->dev))
263 return;
264
265 list_for_each_entry(key, &sdata->key_list, list)
266 ieee80211_key_enable_hw_accel(key);
267}
268
269void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
270{
271 struct ieee80211_key *key;
272
273 list_for_each_entry(key, &sdata->key_list, list)
274 ieee80211_key_disable_hw_accel(key);
275}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 976b646a40de..ba94f58ba02e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -528,7 +528,7 @@ ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
528 528
529 /* Check for weak IVs, if hwaccel did not remove IV from the frame */ 529 /* Check for weak IVs, if hwaccel did not remove IV from the frame */
530 if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) || 530 if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) ||
531 (rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) 531 !(rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
532 if (ieee80211_wep_is_weak_iv(rx->skb, rx->key)) 532 if (ieee80211_wep_is_weak_iv(rx->skb, rx->key))
533 rx->sta->wep_weak_iv_count++; 533 rx->sta->wep_weak_iv_count++;
534 534
@@ -553,7 +553,7 @@ ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx)
553 } 553 }
554 554
555 if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) || 555 if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) ||
556 (rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { 556 !(rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
557 if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) { 557 if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
558 if (net_ratelimit()) 558 if (net_ratelimit())
559 printk(KERN_DEBUG "%s: RX WEP frame, decrypt " 559 printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
@@ -897,8 +897,7 @@ ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
897 * uploaded to the hardware. 897 * uploaded to the hardware.
898 */ 898 */
899 if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) && 899 if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) &&
900 (!rx->key || 900 (!rx->key || (rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)))
901 !(rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)))
902 return TXRX_CONTINUE; 901 return TXRX_CONTINUE;
903 902
904 /* Drop unencrypted frames if key is set. */ 903 /* Drop unencrypted frames if key is set. */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index fba2d79e4d2b..c17172abb21c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -19,7 +19,6 @@
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "ieee80211_rate.h" 20#include "ieee80211_rate.h"
21#include "sta_info.h" 21#include "sta_info.h"
22#include "debugfs_key.h"
23#include "debugfs_sta.h" 22#include "debugfs_sta.h"
24 23
25/* Caller must hold local->sta_lock */ 24/* Caller must hold local->sta_lock */
@@ -118,8 +117,6 @@ static void sta_info_release(struct kref *kref)
118 } 117 }
119 rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); 118 rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
120 rate_control_put(sta->rate_ctrl); 119 rate_control_put(sta->rate_ctrl);
121 if (sta->key)
122 ieee80211_debugfs_key_sta_del(sta->key, sta);
123 kfree(sta); 120 kfree(sta);
124} 121}
125 122
@@ -230,11 +227,8 @@ void sta_info_free(struct sta_info *sta)
230 local->mdev->name, MAC_ARG(sta->addr)); 227 local->mdev->name, MAC_ARG(sta->addr));
231#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 228#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
232 229
233 if (sta->key) { 230 ieee80211_key_free(sta->key);
234 ieee80211_debugfs_key_remove(sta->key); 231 sta->key = NULL;
235 ieee80211_key_free(sta->key);
236 sta->key = NULL;
237 }
238 232
239 rate_control_remove_sta_debugfs(sta); 233 rate_control_remove_sta_debugfs(sta);
240 ieee80211_sta_debugfs_remove(sta); 234 ieee80211_sta_debugfs_remove(sta);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index d70140cbd66a..b65ff6536244 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -536,7 +536,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
536 536
537static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb) 537static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
538{ 538{
539 if (tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) { 539 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
540 if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) 540 if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
541 return -1; 541 return -1;
542 } else { 542 } else {
@@ -832,7 +832,7 @@ __ieee80211_parse_tx_radiotap(
832 */ 832 */
833 833
834 control->retry_limit = 1; /* no retry */ 834 control->retry_limit = 1; /* no retry */
835 control->key_idx = -1; /* no encryption key */ 835 control->key_idx = HW_KEY_IDX_INVALID;
836 control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | 836 control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
837 IEEE80211_TXCTL_USE_CTS_PROTECT); 837 IEEE80211_TXCTL_USE_CTS_PROTECT);
838 control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT | 838 control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 4a2a9aa638b3..b6cd66e0ee58 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -89,7 +89,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
89 if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) 89 if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
90 return TXRX_DROP; 90 return TXRX_DROP;
91 91
92 if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && 92 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
93 !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) && 93 !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) &&
94 !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) && 94 !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) &&
95 !wpa_test) { 95 !wpa_test) {
@@ -146,7 +146,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
146 return TXRX_CONTINUE; 146 return TXRX_CONTINUE;
147 147
148 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && 148 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
149 !(rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { 149 (rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
150 if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) { 150 if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
151 if (skb->len < MICHAEL_MIC_LEN) 151 if (skb->len < MICHAEL_MIC_LEN)
152 return TXRX_DROP; 152 return TXRX_DROP;
@@ -205,10 +205,10 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
205 hdrlen = ieee80211_get_hdrlen(fc); 205 hdrlen = ieee80211_get_hdrlen(fc);
206 len = skb->len - hdrlen; 206 len = skb->len - hdrlen;
207 207
208 if (tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) 208 if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
209 tailneed = TKIP_ICV_LEN;
210 else
211 tailneed = 0; 209 tailneed = 0;
210 else
211 tailneed = TKIP_ICV_LEN;
212 212
213 if ((skb_headroom(skb) < TKIP_IV_LEN || 213 if ((skb_headroom(skb) < TKIP_IV_LEN ||
214 skb_tailroom(skb) < tailneed)) { 214 skb_tailroom(skb) < tailneed)) {
@@ -227,7 +227,7 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
227 if (key->u.tkip.iv16 == 0) 227 if (key->u.tkip.iv16 == 0)
228 key->u.tkip.iv32++; 228 key->u.tkip.iv32++;
229 229
230 if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { 230 if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
231 u32 flags = tx->local->hw.flags; 231 u32 flags = tx->local->hw.flags;
232 hdr = (struct ieee80211_hdr *)skb->data; 232 hdr = (struct ieee80211_hdr *)skb->data;
233 233
@@ -286,7 +286,7 @@ ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx)
286 tx->u.tx.control->iv_len = TKIP_IV_LEN; 286 tx->u.tx.control->iv_len = TKIP_IV_LEN;
287 ieee80211_tx_set_iswep(tx); 287 ieee80211_tx_set_iswep(tx);
288 288
289 if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && 289 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
290 !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) && 290 !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
291 !wpa_test) { 291 !wpa_test) {
292 /* hwaccel - with no need for preallocated room for IV/ICV */ 292 /* hwaccel - with no need for preallocated room for IV/ICV */
@@ -331,7 +331,7 @@ ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx)
331 return TXRX_DROP; 331 return TXRX_DROP;
332 332
333 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && 333 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
334 !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { 334 (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
335 if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { 335 if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
336 /* Hardware takes care of all processing, including 336 /* Hardware takes care of all processing, including
337 * replay protection, so no need to continue here. */ 337 * replay protection, so no need to continue here. */
@@ -475,10 +475,10 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
475 hdrlen = ieee80211_get_hdrlen(fc); 475 hdrlen = ieee80211_get_hdrlen(fc);
476 len = skb->len - hdrlen; 476 len = skb->len - hdrlen;
477 477
478 if (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) 478 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
479 tailneed = CCMP_MIC_LEN;
480 else
481 tailneed = 0; 479 tailneed = 0;
480 else
481 tailneed = CCMP_MIC_LEN;
482 482
483 if ((skb_headroom(skb) < CCMP_HDR_LEN || 483 if ((skb_headroom(skb) < CCMP_HDR_LEN ||
484 skb_tailroom(skb) < tailneed)) { 484 skb_tailroom(skb) < tailneed)) {
@@ -504,7 +504,7 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
504 504
505 ccmp_pn2hdr(pos, pn, key->conf.keyidx); 505 ccmp_pn2hdr(pos, pn, key->conf.keyidx);
506 506
507 if (!(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { 507 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
508 /* hwaccel - with preallocated room for CCMP header */ 508 /* hwaccel - with preallocated room for CCMP header */
509 tx->u.tx.control->key_idx = key->conf.hw_key_idx; 509 tx->u.tx.control->key_idx = key->conf.hw_key_idx;
510 return 0; 510 return 0;
@@ -537,7 +537,7 @@ ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx)
537 tx->u.tx.control->iv_len = CCMP_HDR_LEN; 537 tx->u.tx.control->iv_len = CCMP_HDR_LEN;
538 ieee80211_tx_set_iswep(tx); 538 ieee80211_tx_set_iswep(tx);
539 539
540 if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && 540 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
541 !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { 541 !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
542 /* hwaccel - with no need for preallocated room for CCMP " 542 /* hwaccel - with no need for preallocated room for CCMP "
543 * header or MIC fields */ 543 * header or MIC fields */
@@ -586,7 +586,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx)
586 return TXRX_DROP; 586 return TXRX_DROP;
587 587
588 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && 588 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
589 !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && 589 (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
590 !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) 590 !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
591 return TXRX_CONTINUE; 591 return TXRX_CONTINUE;
592 592
@@ -607,7 +607,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx)
607 } 607 }
608 608
609 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && 609 if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
610 !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { 610 (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
611 /* hwaccel has already decrypted frame and verified MIC */ 611 /* hwaccel has already decrypted frame and verified MIC */
612 } else { 612 } else {
613 u8 *scratch, *b_0, *aad; 613 u8 *scratch, *b_0, *aad;