aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c31
-rw-r--r--net/mac80211/ieee80211_i.h10
-rw-r--r--net/mac80211/iface.c5
-rw-r--r--net/mac80211/key.c58
-rw-r--r--net/mac80211/key.h13
-rw-r--r--net/mac80211/main.c145
-rw-r--r--net/mac80211/mesh_hwmp.c4
-rw-r--r--net/mac80211/mlme.c4
-rw-r--r--net/mac80211/rx.c65
-rw-r--r--net/mac80211/sta_info.h10
-rw-r--r--net/mac80211/tx.c14
-rw-r--r--net/mac80211/util.c68
-rw-r--r--net/mac80211/wpa.c116
-rw-r--r--net/mac80211/wpa.h2
14 files changed, 444 insertions, 101 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5232b0102143..f6b9265cf04e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -133,7 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
133 struct key_params *params) 133 struct key_params *params)
134{ 134{
135 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 135 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
136 struct ieee80211_local *local = sdata->local;
136 struct sta_info *sta = NULL; 137 struct sta_info *sta = NULL;
138 const struct ieee80211_cipher_scheme *cs = NULL;
137 struct ieee80211_key *key; 139 struct ieee80211_key *key;
138 int err; 140 int err;
139 141
@@ -145,22 +147,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
145 case WLAN_CIPHER_SUITE_WEP40: 147 case WLAN_CIPHER_SUITE_WEP40:
146 case WLAN_CIPHER_SUITE_TKIP: 148 case WLAN_CIPHER_SUITE_TKIP:
147 case WLAN_CIPHER_SUITE_WEP104: 149 case WLAN_CIPHER_SUITE_WEP104:
148 if (IS_ERR(sdata->local->wep_tx_tfm)) 150 if (IS_ERR(local->wep_tx_tfm))
149 return -EINVAL; 151 return -EINVAL;
150 break; 152 break;
153 case WLAN_CIPHER_SUITE_CCMP:
154 case WLAN_CIPHER_SUITE_AES_CMAC:
155 case WLAN_CIPHER_SUITE_GCMP:
156 break;
151 default: 157 default:
158 cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
152 break; 159 break;
153 } 160 }
154 161
155 key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, 162 key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
156 params->key, params->seq_len, params->seq); 163 params->key, params->seq_len, params->seq,
164 cs);
157 if (IS_ERR(key)) 165 if (IS_ERR(key))
158 return PTR_ERR(key); 166 return PTR_ERR(key);
159 167
160 if (pairwise) 168 if (pairwise)
161 key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; 169 key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
162 170
163 mutex_lock(&sdata->local->sta_mtx); 171 mutex_lock(&local->sta_mtx);
164 172
165 if (mac_addr) { 173 if (mac_addr) {
166 if (ieee80211_vif_is_mesh(&sdata->vif)) 174 if (ieee80211_vif_is_mesh(&sdata->vif))
@@ -216,10 +224,13 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
216 break; 224 break;
217 } 225 }
218 226
227 if (sta)
228 sta->cipher_scheme = cs;
229
219 err = ieee80211_key_link(key, sdata, sta); 230 err = ieee80211_key_link(key, sdata, sta);
220 231
221 out_unlock: 232 out_unlock:
222 mutex_unlock(&sdata->local->sta_mtx); 233 mutex_unlock(&local->sta_mtx);
223 234
224 return err; 235 return err;
225} 236}
@@ -244,7 +255,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
244 goto out_unlock; 255 goto out_unlock;
245 256
246 if (pairwise) 257 if (pairwise)
247 key = key_mtx_dereference(local, sta->ptk); 258 key = key_mtx_dereference(local, sta->ptk[key_idx]);
248 else 259 else
249 key = key_mtx_dereference(local, sta->gtk[key_idx]); 260 key = key_mtx_dereference(local, sta->gtk[key_idx]);
250 } else 261 } else
@@ -291,7 +302,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
291 goto out; 302 goto out;
292 303
293 if (pairwise) 304 if (pairwise)
294 key = rcu_dereference(sta->ptk); 305 key = rcu_dereference(sta->ptk[key_idx]);
295 else if (key_idx < NUM_DEFAULT_KEYS) 306 else if (key_idx < NUM_DEFAULT_KEYS)
296 key = rcu_dereference(sta->gtk[key_idx]); 307 key = rcu_dereference(sta->gtk[key_idx]);
297 } else 308 } else
@@ -968,11 +979,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
968 */ 979 */
969 sdata->control_port_protocol = params->crypto.control_port_ethertype; 980 sdata->control_port_protocol = params->crypto.control_port_ethertype;
970 sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; 981 sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
982 sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
983 &params->crypto,
984 sdata->vif.type);
985
971 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { 986 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
972 vlan->control_port_protocol = 987 vlan->control_port_protocol =
973 params->crypto.control_port_ethertype; 988 params->crypto.control_port_ethertype;
974 vlan->control_port_no_encrypt = 989 vlan->control_port_no_encrypt =
975 params->crypto.control_port_no_encrypt; 990 params->crypto.control_port_no_encrypt;
991 vlan->encrypt_headroom =
992 ieee80211_cs_headroom(sdata->local,
993 &params->crypto,
994 vlan->vif.type);
976 } 995 }
977 996
978 sdata->vif.bss_conf.beacon_int = params->beacon_interval; 997 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 29dc505be125..16f5ba4a3252 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -728,6 +728,7 @@ struct ieee80211_sub_if_data {
728 u16 sequence_number; 728 u16 sequence_number;
729 __be16 control_port_protocol; 729 __be16 control_port_protocol;
730 bool control_port_no_encrypt; 730 bool control_port_no_encrypt;
731 int encrypt_headroom;
731 732
732 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; 733 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
733 734
@@ -1749,6 +1750,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work);
1749int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, 1750int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
1750 struct cfg80211_csa_settings *csa_settings); 1751 struct cfg80211_csa_settings *csa_settings);
1751 1752
1753bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs);
1754bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n);
1755const struct ieee80211_cipher_scheme *
1756ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
1757 enum nl80211_iftype iftype);
1758int ieee80211_cs_headroom(struct ieee80211_local *local,
1759 struct cfg80211_crypto_settings *crypto,
1760 enum nl80211_iftype iftype);
1761
1752#ifdef CONFIG_MAC80211_NOINLINE 1762#ifdef CONFIG_MAC80211_NOINLINE
1753#define debug_noinline noinline 1763#define debug_noinline noinline
1754#else 1764#else
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c9b04425ffc7..a851bf4f05e5 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -401,6 +401,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
401 snprintf(sdata->name, IFNAMSIZ, "%s-monitor", 401 snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
402 wiphy_name(local->hw.wiphy)); 402 wiphy_name(local->hw.wiphy));
403 403
404 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
405
404 ieee80211_set_default_queues(sdata); 406 ieee80211_set_default_queues(sdata);
405 407
406 ret = drv_add_interface(local, sdata); 408 ret = drv_add_interface(local, sdata);
@@ -1273,6 +1275,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
1273 1275
1274 sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); 1276 sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
1275 sdata->control_port_no_encrypt = false; 1277 sdata->control_port_no_encrypt = false;
1278 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1276 1279
1277 sdata->noack_map = 0; 1280 sdata->noack_map = 0;
1278 1281
@@ -1689,6 +1692,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1689 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; 1692 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1690 sdata->user_power_level = local->user_power_level; 1693 sdata->user_power_level = local->user_power_level;
1691 1694
1695 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1696
1692 /* setup type-dependent data */ 1697 /* setup type-dependent data */
1693 ieee80211_setup_sdata(sdata, type); 1698 ieee80211_setup_sdata(sdata, type);
1694 1699
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ab8468047200..e568d98167d0 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -267,22 +267,22 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
267 if (new) 267 if (new)
268 list_add_tail(&new->list, &sdata->key_list); 268 list_add_tail(&new->list, &sdata->key_list);
269 269
270 if (sta && pairwise) { 270 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
271 rcu_assign_pointer(sta->ptk, new);
272 } else if (sta) {
273 if (old)
274 idx = old->conf.keyidx;
275 else
276 idx = new->conf.keyidx;
277 rcu_assign_pointer(sta->gtk[idx], new);
278 } else {
279 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
280 271
281 if (old) 272 if (old)
282 idx = old->conf.keyidx; 273 idx = old->conf.keyidx;
283 else 274 else
284 idx = new->conf.keyidx; 275 idx = new->conf.keyidx;
285 276
277 if (sta) {
278 if (pairwise) {
279 rcu_assign_pointer(sta->ptk[idx], new);
280 sta->ptk_idx = idx;
281 } else {
282 rcu_assign_pointer(sta->gtk[idx], new);
283 sta->gtk_idx = idx;
284 }
285 } else {
286 defunikey = old && 286 defunikey = old &&
287 old == key_mtx_dereference(sdata->local, 287 old == key_mtx_dereference(sdata->local,
288 sdata->default_unicast_key); 288 sdata->default_unicast_key);
@@ -316,9 +316,11 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
316 list_del(&old->list); 316 list_del(&old->list);
317} 317}
318 318
319struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, 319struct ieee80211_key *
320 const u8 *key_data, 320ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
321 size_t seq_len, const u8 *seq) 321 const u8 *key_data,
322 size_t seq_len, const u8 *seq,
323 const struct ieee80211_cipher_scheme *cs)
322{ 324{
323 struct ieee80211_key *key; 325 struct ieee80211_key *key;
324 int i, j, err; 326 int i, j, err;
@@ -397,6 +399,18 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
397 return ERR_PTR(err); 399 return ERR_PTR(err);
398 } 400 }
399 break; 401 break;
402 default:
403 if (cs) {
404 size_t len = (seq_len > MAX_PN_LEN) ?
405 MAX_PN_LEN : seq_len;
406
407 key->conf.iv_len = cs->hdr_len;
408 key->conf.icv_len = cs->mic_len;
409 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
410 for (j = 0; j < len; j++)
411 key->u.gen.rx_pn[i][j] =
412 seq[len - j - 1];
413 }
400 } 414 }
401 memcpy(key->conf.key, key_data, key_len); 415 memcpy(key->conf.key, key_data, key_len);
402 INIT_LIST_HEAD(&key->list); 416 INIT_LIST_HEAD(&key->list);
@@ -479,7 +493,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
479 mutex_lock(&sdata->local->key_mtx); 493 mutex_lock(&sdata->local->key_mtx);
480 494
481 if (sta && pairwise) 495 if (sta && pairwise)
482 old_key = key_mtx_dereference(sdata->local, sta->ptk); 496 old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
483 else if (sta) 497 else if (sta)
484 old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); 498 old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
485 else 499 else
@@ -629,8 +643,10 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
629 list_add(&key->list, &keys); 643 list_add(&key->list, &keys);
630 } 644 }
631 645
632 key = key_mtx_dereference(local, sta->ptk); 646 for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
633 if (key) { 647 key = key_mtx_dereference(local, sta->ptk[i]);
648 if (!key)
649 continue;
634 ieee80211_key_replace(key->sdata, key->sta, 650 ieee80211_key_replace(key->sdata, key->sta,
635 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, 651 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
636 key, NULL); 652 key, NULL);
@@ -881,7 +897,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
881 897
882 key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx, 898 key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
883 keyconf->keylen, keyconf->key, 899 keyconf->keylen, keyconf->key,
884 0, NULL); 900 0, NULL, NULL);
885 if (IS_ERR(key)) 901 if (IS_ERR(key))
886 return ERR_CAST(key); 902 return ERR_CAST(key);
887 903
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index aaae0ed37004..0aebb889caba 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -18,6 +18,7 @@
18 18
19#define NUM_DEFAULT_KEYS 4 19#define NUM_DEFAULT_KEYS 4
20#define NUM_DEFAULT_MGMT_KEYS 2 20#define NUM_DEFAULT_MGMT_KEYS 2
21#define MAX_PN_LEN 16
21 22
22struct ieee80211_local; 23struct ieee80211_local;
23struct ieee80211_sub_if_data; 24struct ieee80211_sub_if_data;
@@ -93,6 +94,10 @@ struct ieee80211_key {
93 u32 replays; /* dot11RSNAStatsCMACReplays */ 94 u32 replays; /* dot11RSNAStatsCMACReplays */
94 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 95 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
95 } aes_cmac; 96 } aes_cmac;
97 struct {
98 /* generic cipher scheme */
99 u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN];
100 } gen;
96 } u; 101 } u;
97 102
98 /* number of times this key has been used */ 103 /* number of times this key has been used */
@@ -113,9 +118,11 @@ struct ieee80211_key {
113 struct ieee80211_key_conf conf; 118 struct ieee80211_key_conf conf;
114}; 119};
115 120
116struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, 121struct ieee80211_key *
117 const u8 *key_data, 122ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
118 size_t seq_len, const u8 *seq); 123 const u8 *key_data,
124 size_t seq_len, const u8 *seq,
125 const struct ieee80211_cipher_scheme *cs);
119/* 126/*
120 * Insert a key into data structures (sdata, sta if necessary) 127 * Insert a key into data structures (sdata, sta if necessary)
121 * to make it used, free old key. On failure, also free the new key. 128 * to make it used, free old key. On failure, also free the new key.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 21d5d44444d0..bdb0b6c104b5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -651,15 +651,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
651} 651}
652EXPORT_SYMBOL(ieee80211_alloc_hw); 652EXPORT_SYMBOL(ieee80211_alloc_hw);
653 653
654int ieee80211_register_hw(struct ieee80211_hw *hw) 654static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
655{ 655{
656 struct ieee80211_local *local = hw_to_local(hw); 656 bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
657 int result, i; 657 IS_ERR(local->wep_rx_tfm));
658 enum ieee80211_band band; 658 bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE;
659 int channels, max_bitrates; 659 const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes;
660 bool supp_ht, supp_vht; 660 int n_suites = 0, r = 0, w = 0;
661 netdev_features_t feature_whitelist; 661 u32 *suites;
662 struct cfg80211_chan_def dflt_chandef = {};
663 static const u32 cipher_suites[] = { 662 static const u32 cipher_suites[] = {
664 /* keep WEP first, it may be removed below */ 663 /* keep WEP first, it may be removed below */
665 WLAN_CIPHER_SUITE_WEP40, 664 WLAN_CIPHER_SUITE_WEP40,
@@ -671,6 +670,93 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
671 WLAN_CIPHER_SUITE_AES_CMAC 670 WLAN_CIPHER_SUITE_AES_CMAC
672 }; 671 };
673 672
673 /* Driver specifies the ciphers, we have nothing to do... */
674 if (local->hw.wiphy->cipher_suites && have_wep)
675 return 0;
676
677 /* Set up cipher suites if driver relies on mac80211 cipher defs */
678 if (!local->hw.wiphy->cipher_suites && !cs) {
679 local->hw.wiphy->cipher_suites = cipher_suites;
680 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
681
682 if (!have_mfp)
683 local->hw.wiphy->n_cipher_suites--;
684
685 if (!have_wep) {
686 local->hw.wiphy->cipher_suites += 2;
687 local->hw.wiphy->n_cipher_suites -= 2;
688 }
689
690 return 0;
691 }
692
693 if (!local->hw.wiphy->cipher_suites) {
694 /*
695 * Driver specifies cipher schemes only
696 * We start counting ciphers defined by schemes, TKIP and CCMP
697 */
698 n_suites = local->hw.n_cipher_schemes + 2;
699
700 /* check if we have WEP40 and WEP104 */
701 if (have_wep)
702 n_suites += 2;
703
704 /* check if we have AES_CMAC */
705 if (have_mfp)
706 n_suites++;
707
708 suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
709 if (!suites)
710 return -ENOMEM;
711
712 suites[w++] = WLAN_CIPHER_SUITE_CCMP;
713 suites[w++] = WLAN_CIPHER_SUITE_TKIP;
714
715 if (have_wep) {
716 suites[w++] = WLAN_CIPHER_SUITE_WEP40;
717 suites[w++] = WLAN_CIPHER_SUITE_WEP104;
718 }
719
720 if (have_mfp)
721 suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
722
723 for (r = 0; r < local->hw.n_cipher_schemes; r++)
724 suites[w++] = cs[r].cipher;
725 } else {
726 /* Driver provides cipher suites, but we need to exclude WEP */
727 suites = kmemdup(local->hw.wiphy->cipher_suites,
728 sizeof(u32) * local->hw.wiphy->n_cipher_suites,
729 GFP_KERNEL);
730 if (!suites)
731 return -ENOMEM;
732
733 for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
734 u32 suite = local->hw.wiphy->cipher_suites[r];
735
736 if (suite == WLAN_CIPHER_SUITE_WEP40 ||
737 suite == WLAN_CIPHER_SUITE_WEP104)
738 continue;
739 suites[w++] = suite;
740 }
741 }
742
743 local->hw.wiphy->cipher_suites = suites;
744 local->hw.wiphy->n_cipher_suites = w;
745 local->wiphy_ciphers_allocated = true;
746
747 return 0;
748}
749
750int ieee80211_register_hw(struct ieee80211_hw *hw)
751{
752 struct ieee80211_local *local = hw_to_local(hw);
753 int result, i;
754 enum ieee80211_band band;
755 int channels, max_bitrates;
756 bool supp_ht, supp_vht;
757 netdev_features_t feature_whitelist;
758 struct cfg80211_chan_def dflt_chandef = {};
759
674 if (hw->flags & IEEE80211_HW_QUEUE_CONTROL && 760 if (hw->flags & IEEE80211_HW_QUEUE_CONTROL &&
675 (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE || 761 (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
676 local->hw.offchannel_tx_hw_queue >= local->hw.queues)) 762 local->hw.offchannel_tx_hw_queue >= local->hw.queues))
@@ -851,43 +937,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
851 if (local->hw.wiphy->max_scan_ie_len) 937 if (local->hw.wiphy->max_scan_ie_len)
852 local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; 938 local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
853 939
854 /* Set up cipher suites unless driver already did */ 940 WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes,
855 if (!local->hw.wiphy->cipher_suites) { 941 local->hw.n_cipher_schemes));
856 local->hw.wiphy->cipher_suites = cipher_suites; 942
857 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 943 result = ieee80211_init_cipher_suites(local);
858 if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) 944 if (result < 0)
859 local->hw.wiphy->n_cipher_suites--; 945 goto fail_wiphy_register;
860 }
861 if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
862 if (local->hw.wiphy->cipher_suites == cipher_suites) {
863 local->hw.wiphy->cipher_suites += 2;
864 local->hw.wiphy->n_cipher_suites -= 2;
865 } else {
866 u32 *suites;
867 int r, w = 0;
868
869 /* Filter out WEP */
870
871 suites = kmemdup(
872 local->hw.wiphy->cipher_suites,
873 sizeof(u32) * local->hw.wiphy->n_cipher_suites,
874 GFP_KERNEL);
875 if (!suites) {
876 result = -ENOMEM;
877 goto fail_wiphy_register;
878 }
879 for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
880 u32 suite = local->hw.wiphy->cipher_suites[r];
881 if (suite == WLAN_CIPHER_SUITE_WEP40 ||
882 suite == WLAN_CIPHER_SUITE_WEP104)
883 continue;
884 suites[w++] = suite;
885 }
886 local->hw.wiphy->cipher_suites = suites;
887 local->hw.wiphy->n_cipher_suites = w;
888 local->wiphy_ciphers_allocated = true;
889 }
890 }
891 946
892 if (!local->ops->remain_on_channel) 947 if (!local->ops->remain_on_channel)
893 local->hw.wiphy->max_remain_on_channel_duration = 5000; 948 local->hw.wiphy->max_remain_on_channel_duration = 5000;
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 486819cd02cd..56e0c072007a 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -254,13 +254,13 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
254 return -EAGAIN; 254 return -EAGAIN;
255 255
256 skb = dev_alloc_skb(local->tx_headroom + 256 skb = dev_alloc_skb(local->tx_headroom +
257 IEEE80211_ENCRYPT_HEADROOM + 257 sdata->encrypt_headroom +
258 IEEE80211_ENCRYPT_TAILROOM + 258 IEEE80211_ENCRYPT_TAILROOM +
259 hdr_len + 259 hdr_len +
260 2 + 15 /* PERR IE */); 260 2 + 15 /* PERR IE */);
261 if (!skb) 261 if (!skb)
262 return -1; 262 return -1;
263 skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); 263 skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom);
264 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); 264 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
265 memset(mgmt, 0, hdr_len); 265 memset(mgmt, 0, hdr_len);
266 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 266 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d39d27feb594..f8dca58b7e52 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1747,6 +1747,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1747 1747
1748 ifmgd->flags = 0; 1748 ifmgd->flags = 0;
1749 ieee80211_vif_release_channel(sdata); 1749 ieee80211_vif_release_channel(sdata);
1750
1751 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1750} 1752}
1751 1753
1752void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1754void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -4191,6 +4193,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4191 4193
4192 sdata->control_port_protocol = req->crypto.control_port_ethertype; 4194 sdata->control_port_protocol = req->crypto.control_port_ethertype;
4193 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; 4195 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
4196 sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
4197 sdata->vif.type);
4194 4198
4195 /* kick off associate process */ 4199 /* kick off associate process */
4196 4200
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 401f3c26e707..79f76791f77a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -638,6 +638,27 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
638 return le16_to_cpu(mmie->key_id); 638 return le16_to_cpu(mmie->key_id);
639} 639}
640 640
641static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
642 struct sk_buff *skb)
643{
644 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
645 __le16 fc;
646 int hdrlen;
647 u8 keyid;
648
649 fc = hdr->frame_control;
650 hdrlen = ieee80211_hdrlen(fc);
651
652 if (skb->len < hdrlen + cs->hdr_len)
653 return -EINVAL;
654
655 skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
656 keyid &= cs->key_idx_mask;
657 keyid >>= cs->key_idx_shift;
658
659 return keyid;
660}
661
641static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) 662static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
642{ 663{
643 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 664 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
@@ -1360,6 +1381,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1360 struct ieee80211_key *sta_ptk = NULL; 1381 struct ieee80211_key *sta_ptk = NULL;
1361 int mmie_keyidx = -1; 1382 int mmie_keyidx = -1;
1362 __le16 fc; 1383 __le16 fc;
1384 const struct ieee80211_cipher_scheme *cs = NULL;
1363 1385
1364 /* 1386 /*
1365 * Key selection 101 1387 * Key selection 101
@@ -1397,11 +1419,19 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1397 1419
1398 /* start without a key */ 1420 /* start without a key */
1399 rx->key = NULL; 1421 rx->key = NULL;
1422 fc = hdr->frame_control;
1400 1423
1401 if (rx->sta) 1424 if (rx->sta) {
1402 sta_ptk = rcu_dereference(rx->sta->ptk); 1425 int keyid = rx->sta->ptk_idx;
1403 1426
1404 fc = hdr->frame_control; 1427 if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
1428 cs = rx->sta->cipher_scheme;
1429 keyid = iwl80211_get_cs_keyid(cs, rx->skb);
1430 if (unlikely(keyid < 0))
1431 return RX_DROP_UNUSABLE;
1432 }
1433 sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
1434 }
1405 1435
1406 if (!ieee80211_has_protected(fc)) 1436 if (!ieee80211_has_protected(fc))
1407 mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); 1437 mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
@@ -1463,6 +1493,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1463 return RX_CONTINUE; 1493 return RX_CONTINUE;
1464 } else { 1494 } else {
1465 u8 keyid; 1495 u8 keyid;
1496
1466 /* 1497 /*
1467 * The device doesn't give us the IV so we won't be 1498 * The device doesn't give us the IV so we won't be
1468 * able to look up the key. That's ok though, we 1499 * able to look up the key. That's ok though, we
@@ -1478,15 +1509,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1478 1509
1479 hdrlen = ieee80211_hdrlen(fc); 1510 hdrlen = ieee80211_hdrlen(fc);
1480 1511
1481 if (rx->skb->len < 8 + hdrlen) 1512 if (cs) {
1482 return RX_DROP_UNUSABLE; /* TODO: count this? */ 1513 keyidx = iwl80211_get_cs_keyid(cs, rx->skb);
1483 1514
1484 /* 1515 if (unlikely(keyidx < 0))
1485 * no need to call ieee80211_wep_get_keyidx, 1516 return RX_DROP_UNUSABLE;
1486 * it verifies a bunch of things we've done already 1517 } else {
1487 */ 1518 if (rx->skb->len < 8 + hdrlen)
1488 skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); 1519 return RX_DROP_UNUSABLE; /* TODO: count this? */
1489 keyidx = keyid >> 6; 1520 /*
1521 * no need to call ieee80211_wep_get_keyidx,
1522 * it verifies a bunch of things we've done already
1523 */
1524 skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
1525 keyidx = keyid >> 6;
1526 }
1490 1527
1491 /* check per-station GTK first, if multicast packet */ 1528 /* check per-station GTK first, if multicast packet */
1492 if (is_multicast_ether_addr(hdr->addr1) && rx->sta) 1529 if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
@@ -1534,11 +1571,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1534 result = ieee80211_crypto_aes_cmac_decrypt(rx); 1571 result = ieee80211_crypto_aes_cmac_decrypt(rx);
1535 break; 1572 break;
1536 default: 1573 default:
1537 /* 1574 result = ieee80211_crypto_hw_decrypt(rx);
1538 * We can reach here only with HW-only algorithms
1539 * but why didn't it decrypt the frame?!
1540 */
1541 return RX_DROP_UNUSABLE;
1542 } 1575 }
1543 1576
1544 /* the hdr variable is invalid after the decrypt handlers */ 1577 /* the hdr variable is invalid after the decrypt handlers */
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 3ef06a26b9cb..6b0d6c2dcba7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -231,8 +231,10 @@ struct sta_ampdu_mlme {
231 * @hnext: hash table linked list pointer 231 * @hnext: hash table linked list pointer
232 * @local: pointer to the global information 232 * @local: pointer to the global information
233 * @sdata: virtual interface this station belongs to 233 * @sdata: virtual interface this station belongs to
234 * @ptk: peer key negotiated with this station, if any 234 * @ptk: peer keys negotiated with this station, if any
235 * @ptk_idx: last installed peer key index
235 * @gtk: group keys negotiated with this station, if any 236 * @gtk: group keys negotiated with this station, if any
237 * @gtk_idx: last installed group key index
236 * @rate_ctrl: rate control algorithm reference 238 * @rate_ctrl: rate control algorithm reference
237 * @rate_ctrl_priv: rate control private per-STA pointer 239 * @rate_ctrl_priv: rate control private per-STA pointer
238 * @last_tx_rate: rate used for last transmit, to report to userspace as 240 * @last_tx_rate: rate used for last transmit, to report to userspace as
@@ -303,6 +305,7 @@ struct sta_ampdu_mlme {
303 * @chain_signal_avg: signal average (per chain) 305 * @chain_signal_avg: signal average (per chain)
304 * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for 306 * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
305 * AP only. 307 * AP only.
308 * @cipher_scheme: optional cipher scheme for this station
306 */ 309 */
307struct sta_info { 310struct sta_info {
308 /* General information, mostly static */ 311 /* General information, mostly static */
@@ -312,7 +315,9 @@ struct sta_info {
312 struct ieee80211_local *local; 315 struct ieee80211_local *local;
313 struct ieee80211_sub_if_data *sdata; 316 struct ieee80211_sub_if_data *sdata;
314 struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 317 struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
315 struct ieee80211_key __rcu *ptk; 318 struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
319 u8 gtk_idx;
320 u8 ptk_idx;
316 struct rate_control_ref *rate_ctrl; 321 struct rate_control_ref *rate_ctrl;
317 void *rate_ctrl_priv; 322 void *rate_ctrl_priv;
318 spinlock_t lock; 323 spinlock_t lock;
@@ -414,6 +419,7 @@ struct sta_info {
414 unsigned int beacon_loss_count; 419 unsigned int beacon_loss_count;
415 420
416 enum ieee80211_smps_mode known_smps_mode; 421 enum ieee80211_smps_mode known_smps_mode;
422 const struct ieee80211_cipher_scheme *cipher_scheme;
417 423
418 /* keep last! */ 424 /* keep last! */
419 struct ieee80211_sta sta; 425 struct ieee80211_sta sta;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5ad2e8b1f92c..e541856b4007 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -557,7 +557,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
557 557
558 if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) 558 if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
559 tx->key = NULL; 559 tx->key = NULL;
560 else if (tx->sta && (key = rcu_dereference(tx->sta->ptk))) 560 else if (tx->sta &&
561 (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
561 tx->key = key; 562 tx->key = key;
562 else if (ieee80211_is_mgmt(hdr->frame_control) && 563 else if (ieee80211_is_mgmt(hdr->frame_control) &&
563 is_multicast_ether_addr(hdr->addr1) && 564 is_multicast_ether_addr(hdr->addr1) &&
@@ -840,15 +841,16 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
840 rem -= fraglen; 841 rem -= fraglen;
841 tmp = dev_alloc_skb(local->tx_headroom + 842 tmp = dev_alloc_skb(local->tx_headroom +
842 frag_threshold + 843 frag_threshold +
843 IEEE80211_ENCRYPT_HEADROOM + 844 tx->sdata->encrypt_headroom +
844 IEEE80211_ENCRYPT_TAILROOM); 845 IEEE80211_ENCRYPT_TAILROOM);
845 if (!tmp) 846 if (!tmp)
846 return -ENOMEM; 847 return -ENOMEM;
847 848
848 __skb_queue_tail(&tx->skbs, tmp); 849 __skb_queue_tail(&tx->skbs, tmp);
849 850
850 skb_reserve(tmp, local->tx_headroom + 851 skb_reserve(tmp,
851 IEEE80211_ENCRYPT_HEADROOM); 852 local->tx_headroom + tx->sdata->encrypt_headroom);
853
852 /* copy control information */ 854 /* copy control information */
853 memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); 855 memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
854 856
@@ -1485,7 +1487,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
1485 1487
1486 headroom = local->tx_headroom; 1488 headroom = local->tx_headroom;
1487 if (may_encrypt) 1489 if (may_encrypt)
1488 headroom += IEEE80211_ENCRYPT_HEADROOM; 1490 headroom += sdata->encrypt_headroom;
1489 headroom -= skb_headroom(skb); 1491 headroom -= skb_headroom(skb);
1490 headroom = max_t(int, 0, headroom); 1492 headroom = max_t(int, 0, headroom);
1491 1493
@@ -2108,7 +2110,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
2108 */ 2110 */
2109 2111
2110 if (head_need > 0 || skb_cloned(skb)) { 2112 if (head_need > 0 || skb_cloned(skb)) {
2111 head_need += IEEE80211_ENCRYPT_HEADROOM; 2113 head_need += sdata->encrypt_headroom;
2112 head_need += local->tx_headroom; 2114 head_need += local->tx_headroom;
2113 head_need = max_t(int, 0, head_need); 2115 head_need = max_t(int, 0, head_need);
2114 if (ieee80211_skb_resize(sdata, skb, head_need, true)) { 2116 if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index fd4fe5d61782..5dfa41abdf8b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2475,3 +2475,71 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
2475 ieee80211_tx_skb(sdata, skb); 2475 ieee80211_tx_skb(sdata, skb);
2476 return 0; 2476 return 0;
2477} 2477}
2478
2479bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs)
2480{
2481 return !(cs == NULL || cs->cipher == 0 ||
2482 cs->hdr_len < cs->pn_len + cs->pn_off ||
2483 cs->hdr_len <= cs->key_idx_off ||
2484 cs->key_idx_shift > 7 ||
2485 cs->key_idx_mask == 0);
2486}
2487
2488bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n)
2489{
2490 int i;
2491
2492 /* Ensure we have enough iftype bitmap space for all iftype values */
2493 WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype));
2494
2495 for (i = 0; i < n; i++)
2496 if (!ieee80211_cs_valid(&cs[i]))
2497 return false;
2498
2499 return true;
2500}
2501
2502const struct ieee80211_cipher_scheme *
2503ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
2504 enum nl80211_iftype iftype)
2505{
2506 const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes;
2507 int n = local->hw.n_cipher_schemes;
2508 int i;
2509 const struct ieee80211_cipher_scheme *cs = NULL;
2510
2511 for (i = 0; i < n; i++) {
2512 if (l[i].cipher == cipher) {
2513 cs = &l[i];
2514 break;
2515 }
2516 }
2517
2518 if (!cs || !(cs->iftype & BIT(iftype)))
2519 return NULL;
2520
2521 return cs;
2522}
2523
2524int ieee80211_cs_headroom(struct ieee80211_local *local,
2525 struct cfg80211_crypto_settings *crypto,
2526 enum nl80211_iftype iftype)
2527{
2528 const struct ieee80211_cipher_scheme *cs;
2529 int headroom = IEEE80211_ENCRYPT_HEADROOM;
2530 int i;
2531
2532 for (i = 0; i < crypto->n_ciphers_pairwise; i++) {
2533 cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i],
2534 iftype);
2535
2536 if (cs && headroom < cs->hdr_len)
2537 headroom = cs->hdr_len;
2538 }
2539
2540 cs = ieee80211_cs_get(local, crypto->cipher_group, iftype);
2541 if (cs && headroom < cs->hdr_len)
2542 headroom = cs->hdr_len;
2543
2544 return headroom;
2545}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index d65728220763..7313d379c0d3 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -545,6 +545,106 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
545 return RX_CONTINUE; 545 return RX_CONTINUE;
546} 546}
547 547
548static ieee80211_tx_result
549ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
550 struct sk_buff *skb)
551{
552 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
553 struct ieee80211_key *key = tx->key;
554 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
555 const struct ieee80211_cipher_scheme *cs = key->sta->cipher_scheme;
556 int hdrlen;
557 u8 *pos;
558
559 if (info->control.hw_key &&
560 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
561 /* hwaccel has no need for preallocated head room */
562 return TX_CONTINUE;
563 }
564
565 if (unlikely(skb_headroom(skb) < cs->hdr_len &&
566 pskb_expand_head(skb, cs->hdr_len, 0, GFP_ATOMIC)))
567 return TX_DROP;
568
569 hdrlen = ieee80211_hdrlen(hdr->frame_control);
570
571 pos = skb_push(skb, cs->hdr_len);
572 memmove(pos, pos + cs->hdr_len, hdrlen);
573 skb_set_network_header(skb, skb_network_offset(skb) + cs->hdr_len);
574
575 return TX_CONTINUE;
576}
577
578static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len)
579{
580 int i;
581
582 /* pn is little endian */
583 for (i = len - 1; i >= 0; i--) {
584 if (pn1[i] < pn2[i])
585 return -1;
586 else if (pn1[i] > pn2[i])
587 return 1;
588 }
589
590 return 0;
591}
592
593static ieee80211_rx_result
594ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
595{
596 struct ieee80211_key *key = rx->key;
597 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
598 const struct ieee80211_cipher_scheme *cs = NULL;
599 int hdrlen = ieee80211_hdrlen(hdr->frame_control);
600 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
601 int data_len;
602 u8 *rx_pn;
603 u8 *skb_pn;
604 u8 qos_tid;
605
606 if (!rx->sta || !rx->sta->cipher_scheme ||
607 !(status->flag & RX_FLAG_DECRYPTED))
608 return RX_DROP_UNUSABLE;
609
610 if (!ieee80211_is_data(hdr->frame_control))
611 return RX_CONTINUE;
612
613 cs = rx->sta->cipher_scheme;
614
615 data_len = rx->skb->len - hdrlen - cs->hdr_len;
616
617 if (data_len < 0)
618 return RX_DROP_UNUSABLE;
619
620 if (ieee80211_is_data_qos(hdr->frame_control))
621 qos_tid = *ieee80211_get_qos_ctl(hdr) &
622 IEEE80211_QOS_CTL_TID_MASK;
623 else
624 qos_tid = 0;
625
626 if (skb_linearize(rx->skb))
627 return RX_DROP_UNUSABLE;
628
629 hdr = (struct ieee80211_hdr *)rx->skb->data;
630
631 rx_pn = key->u.gen.rx_pn[qos_tid];
632 skb_pn = rx->skb->data + hdrlen + cs->pn_off;
633
634 if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0)
635 return RX_DROP_UNUSABLE;
636
637 memcpy(rx_pn, skb_pn, cs->pn_len);
638
639 /* remove security header and MIC */
640 if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len))
641 return RX_DROP_UNUSABLE;
642
643 memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen);
644 skb_pull(rx->skb, cs->hdr_len);
645
646 return RX_CONTINUE;
647}
548 648
549static void bip_aad(struct sk_buff *skb, u8 *aad) 649static void bip_aad(struct sk_buff *skb, u8 *aad)
550{ 650{
@@ -685,6 +785,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
685{ 785{
686 struct sk_buff *skb; 786 struct sk_buff *skb;
687 struct ieee80211_tx_info *info = NULL; 787 struct ieee80211_tx_info *info = NULL;
788 ieee80211_tx_result res;
688 789
689 skb_queue_walk(&tx->skbs, skb) { 790 skb_queue_walk(&tx->skbs, skb) {
690 info = IEEE80211_SKB_CB(skb); 791 info = IEEE80211_SKB_CB(skb);
@@ -692,9 +793,24 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
692 /* handle hw-only algorithm */ 793 /* handle hw-only algorithm */
693 if (!info->control.hw_key) 794 if (!info->control.hw_key)
694 return TX_DROP; 795 return TX_DROP;
796
797 if (tx->key->sta->cipher_scheme) {
798 res = ieee80211_crypto_cs_encrypt(tx, skb);
799 if (res != TX_CONTINUE)
800 return res;
801 }
695 } 802 }
696 803
697 ieee80211_tx_set_protected(tx); 804 ieee80211_tx_set_protected(tx);
698 805
699 return TX_CONTINUE; 806 return TX_CONTINUE;
700} 807}
808
809ieee80211_rx_result
810ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx)
811{
812 if (rx->sta->cipher_scheme)
813 return ieee80211_crypto_cs_decrypt(rx);
814
815 return RX_DROP_UNUSABLE;
816}
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
index 07e33f899c71..62e5a12dfe0a 100644
--- a/net/mac80211/wpa.h
+++ b/net/mac80211/wpa.h
@@ -34,5 +34,7 @@ ieee80211_rx_result
34ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); 34ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
35ieee80211_tx_result 35ieee80211_tx_result
36ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); 36ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
37ieee80211_rx_result
38ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);
37 39
38#endif /* WPA_H */ 40#endif /* WPA_H */