aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMax Stepanov <Max.Stepanov@intel.com>2013-03-24 08:23:27 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 14:50:52 -0500
commit2475b1cc0d5283a33144b79f3eba6d401d873962 (patch)
tree5933a46b04abf495b18877ce710f84a4acda2841 /net
parent6bc54fbcee6836f08355fcca76549c22ad2c2940 (diff)
mac80211: add generic cipher scheme support
This adds generic cipher scheme support to mac80211, such schemes are fully under control by the driver. On hw registration drivers may specify additional HW ciphers with a scheme how these ciphers have to be handled by mac80211 TX/RR. A cipher scheme specifies a cipher suite value, a size of the security header to be added to or stripped from frames and how the PN is to be verified on RX. Signed-off-by: Max Stepanov <Max.Stepanov@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-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 */