diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/debugfs_key.c | 4 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 8 | ||||
-rw-r--r-- | net/mac80211/ieee80211_iface.c | 21 | ||||
-rw-r--r-- | net/mac80211/ieee80211_ioctl.c | 177 | ||||
-rw-r--r-- | net/mac80211/ieee80211_key.h | 26 | ||||
-rw-r--r-- | net/mac80211/key.c | 243 | ||||
-rw-r--r-- | net/mac80211/rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 10 | ||||
-rw-r--r-- | net/mac80211/tx.c | 4 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 30 |
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) \ |
30 | static const struct file_operations key_ ##name## _ops = { \ | 31 | static 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) \ |
45 | static const struct file_operations key_ ##name## _ops = { \ | 45 | static const struct file_operations key_ ##name## _ops = { \ |
@@ -54,7 +54,7 @@ static const struct file_operations key_ ##name## _ops = { \ | |||
54 | KEY_CONF_FILE(keylen, D); | 54 | KEY_CONF_FILE(keylen, D); |
55 | KEY_CONF_FILE(keyidx, D); | 55 | KEY_CONF_FILE(keyidx, D); |
56 | KEY_CONF_FILE(hw_key_idx, D); | 56 | KEY_CONF_FILE(hw_key_idx, D); |
57 | KEY_CONF_FILE(flags, X); | 57 | KEY_FILE(flags, X); |
58 | KEY_FILE(tx_rx_count, D); | 58 | KEY_FILE(tx_rx_count, D); |
59 | 59 | ||
60 | static ssize_t key_algorithm_read(struct file *file, | 60 | static 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); | |||
810 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 813 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
811 | int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); | 814 | int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); |
812 | 815 | ||
813 | /* key handling */ | ||
814 | struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata, | ||
815 | int idx, size_t key_len, gfp_t flags); | ||
816 | void ieee80211_key_free(struct ieee80211_key *key); | ||
817 | |||
818 | /* utility functions/constants */ | 816 | /* utility functions/constants */ |
819 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 817 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
820 | extern const unsigned char rfc1042_header[6]; | 818 | extern 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 | ||
30 | static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) | 32 | static 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 | |||
30 | static 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 | ||
51 | static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, | 29 | static 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: | |
234 | err_free: | ||
235 | ieee80211_key_free(key); | ||
236 | err_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 | ||
44 | struct ieee80211_local; | ||
45 | struct ieee80211_sub_if_data; | ||
46 | struct sta_info; | ||
47 | |||
48 | #define KEY_FLAG_UPLOADED_TO_HARDWARE (1<<0) | ||
49 | |||
44 | struct ieee80211_key { | 50 | struct 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 | ||
114 | struct 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); | ||
120 | void ieee80211_key_free(struct ieee80211_key *key); | ||
121 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | ||
122 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | ||
123 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | ||
124 | void 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 | |||
38 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
39 | static const u8 zero_addr[ETH_ALEN]; | ||
40 | |||
41 | static 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 | |||
61 | static 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 | |||
87 | static 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 | |||
16 | struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata, | 114 | struct 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 | |||
228 | void 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 | |||
249 | void 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 | |||
257 | void 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 | |||
269 | void 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 | ||
537 | static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb) | 537 | static 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; |