aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-10-05 13:39:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-06 16:30:40 -0400
commite31b82136d1adc7a599b6e99d3321e5831841f5a (patch)
treec72d78d4cccfd08587e909c7efe59956f1cbc23e /net
parent53f73c09d64f1fa7d7e6e8b6bb7468d42eddc92d (diff)
cfg80211/mac80211: allow per-station GTKs
This adds API to allow adding per-station GTKs, updates mac80211 to support it, and also allows drivers to remove a key from hwaccel again when this may be necessary due to multiple GTKs. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c32
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/key.c95
-rw-r--r--net/mac80211/key.h3
-rw-r--r--net/mac80211/rx.c41
-rw-r--r--net/mac80211/sta_info.c10
-rw-r--r--net/mac80211/sta_info.h6
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/ibss.c2
-rw-r--r--net/wireless/nl80211.c87
-rw-r--r--net/wireless/sme.c2
-rw-r--r--net/wireless/util.c12
-rw-r--r--net/wireless/wext-compat.c38
14 files changed, 239 insertions, 95 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 94bf550bd4c9..8b0e874a3d65 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -103,7 +103,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
103} 103}
104 104
105static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, 105static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
106 u8 key_idx, const u8 *mac_addr, 106 u8 key_idx, bool pairwise, const u8 *mac_addr,
107 struct key_params *params) 107 struct key_params *params)
108{ 108{
109 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 109 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -131,6 +131,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
131 if (IS_ERR(key)) 131 if (IS_ERR(key))
132 return PTR_ERR(key); 132 return PTR_ERR(key);
133 133
134 if (pairwise)
135 key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
136
134 mutex_lock(&sdata->local->sta_mtx); 137 mutex_lock(&sdata->local->sta_mtx);
135 138
136 if (mac_addr) { 139 if (mac_addr) {
@@ -153,7 +156,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
153} 156}
154 157
155static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, 158static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
156 u8 key_idx, const u8 *mac_addr) 159 u8 key_idx, bool pairwise, const u8 *mac_addr)
157{ 160{
158 struct ieee80211_sub_if_data *sdata; 161 struct ieee80211_sub_if_data *sdata;
159 struct sta_info *sta; 162 struct sta_info *sta;
@@ -170,10 +173,17 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
170 if (!sta) 173 if (!sta)
171 goto out_unlock; 174 goto out_unlock;
172 175
173 if (sta->key) { 176 if (pairwise) {
174 ieee80211_key_free(sdata->local, sta->key); 177 if (sta->ptk) {
175 WARN_ON(sta->key); 178 ieee80211_key_free(sdata->local, sta->ptk);
176 ret = 0; 179 ret = 0;
180 }
181 } else {
182 if (sta->gtk[key_idx]) {
183 ieee80211_key_free(sdata->local,
184 sta->gtk[key_idx]);
185 ret = 0;
186 }
177 } 187 }
178 188
179 goto out_unlock; 189 goto out_unlock;
@@ -195,7 +205,8 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
195} 205}
196 206
197static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, 207static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
198 u8 key_idx, const u8 *mac_addr, void *cookie, 208 u8 key_idx, bool pairwise, const u8 *mac_addr,
209 void *cookie,
199 void (*callback)(void *cookie, 210 void (*callback)(void *cookie,
200 struct key_params *params)) 211 struct key_params *params))
201{ 212{
@@ -203,7 +214,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
203 struct sta_info *sta = NULL; 214 struct sta_info *sta = NULL;
204 u8 seq[6] = {0}; 215 u8 seq[6] = {0};
205 struct key_params params; 216 struct key_params params;
206 struct ieee80211_key *key; 217 struct ieee80211_key *key = NULL;
207 u32 iv32; 218 u32 iv32;
208 u16 iv16; 219 u16 iv16;
209 int err = -ENOENT; 220 int err = -ENOENT;
@@ -217,7 +228,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
217 if (!sta) 228 if (!sta)
218 goto out; 229 goto out;
219 230
220 key = sta->key; 231 if (pairwise)
232 key = sta->ptk;
233 else if (key_idx < NUM_DEFAULT_KEYS)
234 key = sta->gtk[key_idx];
221 } else 235 } else
222 key = sdata->keys[key_idx]; 236 key = sdata->keys[key_idx];
223 237
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 76c2b50ec6f8..f0610fa4fbe0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -549,8 +549,6 @@ struct ieee80211_sub_if_data {
549 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; 549 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
550 unsigned int fragment_next; 550 unsigned int fragment_next;
551 551
552#define NUM_DEFAULT_KEYS 4
553#define NUM_DEFAULT_MGMT_KEYS 2
554 struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 552 struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
555 struct ieee80211_key *default_key; 553 struct ieee80211_key *default_key;
556 struct ieee80211_key *default_mgmt_key; 554 struct ieee80211_key *default_mgmt_key;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 6a63d1abd14d..ccd676b2f599 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -68,15 +68,21 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
68 68
69 might_sleep(); 69 might_sleep();
70 70
71 if (!key->local->ops->set_key) { 71 if (!key->local->ops->set_key)
72 ret = -EOPNOTSUPP;
73 goto out_unsupported; 72 goto out_unsupported;
74 }
75 73
76 assert_key_lock(key->local); 74 assert_key_lock(key->local);
77 75
78 sta = get_sta_for_key(key); 76 sta = get_sta_for_key(key);
79 77
78 /*
79 * If this is a per-STA GTK, check if it
80 * is supported; if not, return.
81 */
82 if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
83 !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
84 goto out_unsupported;
85
80 sdata = key->sdata; 86 sdata = key->sdata;
81 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 87 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
82 sdata = container_of(sdata->bss, 88 sdata = container_of(sdata->bss,
@@ -85,31 +91,28 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
85 91
86 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); 92 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
87 93
88 if (!ret) 94 if (!ret) {
89 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 95 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
96 return 0;
97 }
90 98
91 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) 99 if (ret != -ENOSPC && ret != -EOPNOTSUPP)
92 wiphy_err(key->local->hw.wiphy, 100 wiphy_err(key->local->hw.wiphy,
93 "failed to set key (%d, %pM) to hardware (%d)\n", 101 "failed to set key (%d, %pM) to hardware (%d)\n",
94 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); 102 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
95 103
96out_unsupported: 104 out_unsupported:
97 if (ret) { 105 switch (key->conf.cipher) {
98 switch (key->conf.cipher) { 106 case WLAN_CIPHER_SUITE_WEP40:
99 case WLAN_CIPHER_SUITE_WEP40: 107 case WLAN_CIPHER_SUITE_WEP104:
100 case WLAN_CIPHER_SUITE_WEP104: 108 case WLAN_CIPHER_SUITE_TKIP:
101 case WLAN_CIPHER_SUITE_TKIP: 109 case WLAN_CIPHER_SUITE_CCMP:
102 case WLAN_CIPHER_SUITE_CCMP: 110 case WLAN_CIPHER_SUITE_AES_CMAC:
103 case WLAN_CIPHER_SUITE_AES_CMAC: 111 /* all of these we can do in software */
104 /* all of these we can do in software */ 112 return 0;
105 ret = 0; 113 default:
106 break; 114 return -EINVAL;
107 default:
108 ret = -EINVAL;
109 }
110 } 115 }
111
112 return ret;
113} 116}
114 117
115static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) 118static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
@@ -147,6 +150,26 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
147 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 150 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
148} 151}
149 152
153void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
154{
155 struct ieee80211_key *key;
156
157 key = container_of(key_conf, struct ieee80211_key, conf);
158
159 might_sleep();
160 assert_key_lock(key->local);
161
162 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
163
164 /*
165 * Flush TX path to avoid attempts to use this key
166 * after this function returns. Until then, drivers
167 * must be prepared to handle the key.
168 */
169 synchronize_rcu();
170}
171EXPORT_SYMBOL_GPL(ieee80211_key_removed);
172
150static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 173static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
151 int idx) 174 int idx)
152{ 175{
@@ -202,6 +225,7 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
202 225
203static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, 226static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
204 struct sta_info *sta, 227 struct sta_info *sta,
228 bool pairwise,
205 struct ieee80211_key *old, 229 struct ieee80211_key *old,
206 struct ieee80211_key *new) 230 struct ieee80211_key *new)
207{ 231{
@@ -210,8 +234,14 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
210 if (new) 234 if (new)
211 list_add(&new->list, &sdata->key_list); 235 list_add(&new->list, &sdata->key_list);
212 236
213 if (sta) { 237 if (sta && pairwise) {
214 rcu_assign_pointer(sta->key, new); 238 rcu_assign_pointer(sta->ptk, new);
239 } else if (sta) {
240 if (old)
241 idx = old->conf.keyidx;
242 else
243 idx = new->conf.keyidx;
244 rcu_assign_pointer(sta->gtk[idx], new);
215 } else { 245 } else {
216 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); 246 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
217 247
@@ -355,6 +385,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
355{ 385{
356 struct ieee80211_key *old_key; 386 struct ieee80211_key *old_key;
357 int idx, ret; 387 int idx, ret;
388 bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
358 389
359 BUG_ON(!sdata); 390 BUG_ON(!sdata);
360 BUG_ON(!key); 391 BUG_ON(!key);
@@ -371,13 +402,6 @@ int ieee80211_key_link(struct ieee80211_key *key,
371 */ 402 */
372 if (test_sta_flags(sta, WLAN_STA_WME)) 403 if (test_sta_flags(sta, WLAN_STA_WME))
373 key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; 404 key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
374
375 /*
376 * This key is for a specific sta interface,
377 * inform the driver that it should try to store
378 * this key as pairwise key.
379 */
380 key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
381 } else { 405 } else {
382 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 406 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
383 struct sta_info *ap; 407 struct sta_info *ap;
@@ -399,12 +423,14 @@ int ieee80211_key_link(struct ieee80211_key *key,
399 423
400 mutex_lock(&sdata->local->key_mtx); 424 mutex_lock(&sdata->local->key_mtx);
401 425
402 if (sta) 426 if (sta && pairwise)
403 old_key = sta->key; 427 old_key = sta->ptk;
428 else if (sta)
429 old_key = sta->gtk[idx];
404 else 430 else
405 old_key = sdata->keys[idx]; 431 old_key = sdata->keys[idx];
406 432
407 __ieee80211_key_replace(sdata, sta, old_key, key); 433 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
408 __ieee80211_key_destroy(old_key); 434 __ieee80211_key_destroy(old_key);
409 435
410 ieee80211_debugfs_key_add(key); 436 ieee80211_debugfs_key_add(key);
@@ -423,7 +449,8 @@ static void __ieee80211_key_free(struct ieee80211_key *key)
423 */ 449 */
424 if (key->sdata) 450 if (key->sdata)
425 __ieee80211_key_replace(key->sdata, key->sta, 451 __ieee80211_key_replace(key->sdata, key->sta,
426 key, NULL); 452 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
453 key, NULL);
427 __ieee80211_key_destroy(key); 454 __ieee80211_key_destroy(key);
428} 455}
429 456
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index cb9a4a65cc68..0db1c0f5f697 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -16,6 +16,9 @@
16#include <linux/rcupdate.h> 16#include <linux/rcupdate.h>
17#include <net/mac80211.h> 17#include <net/mac80211.h>
18 18
19#define NUM_DEFAULT_KEYS 4
20#define NUM_DEFAULT_MGMT_KEYS 2
21
19#define WEP_IV_LEN 4 22#define WEP_IV_LEN 4
20#define WEP_ICV_LEN 4 23#define WEP_ICV_LEN 4
21#define ALG_TKIP_KEY_LEN 32 24#define ALG_TKIP_KEY_LEN 32
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b3e161ffa4b3..b67221def584 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -846,7 +846,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
846 int keyidx; 846 int keyidx;
847 int hdrlen; 847 int hdrlen;
848 ieee80211_rx_result result = RX_DROP_UNUSABLE; 848 ieee80211_rx_result result = RX_DROP_UNUSABLE;
849 struct ieee80211_key *stakey = NULL; 849 struct ieee80211_key *sta_ptk = NULL;
850 int mmie_keyidx = -1; 850 int mmie_keyidx = -1;
851 __le16 fc; 851 __le16 fc;
852 852
@@ -888,15 +888,15 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
888 rx->key = NULL; 888 rx->key = NULL;
889 889
890 if (rx->sta) 890 if (rx->sta)
891 stakey = rcu_dereference(rx->sta->key); 891 sta_ptk = rcu_dereference(rx->sta->ptk);
892 892
893 fc = hdr->frame_control; 893 fc = hdr->frame_control;
894 894
895 if (!ieee80211_has_protected(fc)) 895 if (!ieee80211_has_protected(fc))
896 mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); 896 mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
897 897
898 if (!is_multicast_ether_addr(hdr->addr1) && stakey) { 898 if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
899 rx->key = stakey; 899 rx->key = sta_ptk;
900 if ((status->flag & RX_FLAG_DECRYPTED) && 900 if ((status->flag & RX_FLAG_DECRYPTED) &&
901 (status->flag & RX_FLAG_IV_STRIPPED)) 901 (status->flag & RX_FLAG_IV_STRIPPED))
902 return RX_CONTINUE; 902 return RX_CONTINUE;
@@ -912,7 +912,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
912 if (mmie_keyidx < NUM_DEFAULT_KEYS || 912 if (mmie_keyidx < NUM_DEFAULT_KEYS ||
913 mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 913 mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
914 return RX_DROP_MONITOR; /* unexpected BIP keyidx */ 914 return RX_DROP_MONITOR; /* unexpected BIP keyidx */
915 rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); 915 if (rx->sta)
916 rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
917 if (!rx->key)
918 rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
916 } else if (!ieee80211_has_protected(fc)) { 919 } else if (!ieee80211_has_protected(fc)) {
917 /* 920 /*
918 * The frame was not protected, so skip decryption. However, we 921 * The frame was not protected, so skip decryption. However, we
@@ -955,17 +958,25 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
955 skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); 958 skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
956 keyidx = keyid >> 6; 959 keyidx = keyid >> 6;
957 960
958 rx->key = rcu_dereference(rx->sdata->keys[keyidx]); 961 /* check per-station GTK first, if multicast packet */
962 if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
963 rx->key = rcu_dereference(rx->sta->gtk[keyidx]);
959 964
960 /* 965 /* if not found, try default key */
961 * RSNA-protected unicast frames should always be sent with 966 if (!rx->key) {
962 * pairwise or station-to-station keys, but for WEP we allow 967 rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
963 * using a key index as well. 968
964 */ 969 /*
965 if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && 970 * RSNA-protected unicast frames should always be
966 rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && 971 * sent with pairwise or station-to-station keys,
967 !is_multicast_ether_addr(hdr->addr1)) 972 * but for WEP we allow using a key index as well.
968 rx->key = NULL; 973 */
974 if (rx->key &&
975 rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 &&
976 rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 &&
977 !is_multicast_ether_addr(hdr->addr1))
978 rx->key = NULL;
979 }
969 } 980 }
970 981
971 if (rx->key) { 982 if (rx->key) {
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aeaf2d6fccc8..6d8f897d8763 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -616,7 +616,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
616 struct ieee80211_sub_if_data *sdata; 616 struct ieee80211_sub_if_data *sdata;
617 struct sk_buff *skb; 617 struct sk_buff *skb;
618 unsigned long flags; 618 unsigned long flags;
619 int ret; 619 int ret, i;
620 620
621 might_sleep(); 621 might_sleep();
622 622
@@ -644,10 +644,10 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
644 if (ret) 644 if (ret)
645 return ret; 645 return ret;
646 646
647 if (sta->key) { 647 for (i = 0; i < NUM_DEFAULT_KEYS; i++)
648 ieee80211_key_free(local, sta->key); 648 ieee80211_key_free(local, sta->gtk[i]);
649 WARN_ON(sta->key); 649 if (sta->ptk)
650 } 650 ieee80211_key_free(local, sta->ptk);
651 651
652 sta->dead = true; 652 sta->dead = true;
653 653
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index cf21a2e8134f..9265acadef32 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -199,7 +199,8 @@ enum plink_state {
199 * @hnext: hash table linked list pointer 199 * @hnext: hash table linked list pointer
200 * @local: pointer to the global information 200 * @local: pointer to the global information
201 * @sdata: virtual interface this station belongs to 201 * @sdata: virtual interface this station belongs to
202 * @key: peer key negotiated with this station, if any 202 * @ptk: peer key negotiated with this station, if any
203 * @gtk: group keys negotiated with this station, if any
203 * @rate_ctrl: rate control algorithm reference 204 * @rate_ctrl: rate control algorithm reference
204 * @rate_ctrl_priv: rate control private per-STA pointer 205 * @rate_ctrl_priv: rate control private per-STA pointer
205 * @last_tx_rate: rate used for last transmit, to report to userspace as 206 * @last_tx_rate: rate used for last transmit, to report to userspace as
@@ -254,7 +255,8 @@ struct sta_info {
254 struct sta_info *hnext; 255 struct sta_info *hnext;
255 struct ieee80211_local *local; 256 struct ieee80211_local *local;
256 struct ieee80211_sub_if_data *sdata; 257 struct ieee80211_sub_if_data *sdata;
257 struct ieee80211_key *key; 258 struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
259 struct ieee80211_key *ptk;
258 struct rate_control_ref *rate_ctrl; 260 struct rate_control_ref *rate_ctrl;
259 void *rate_ctrl_priv; 261 void *rate_ctrl_priv;
260 spinlock_t lock; 262 spinlock_t lock;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 258fbdbedbdf..96c594309506 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -532,7 +532,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
532 532
533 if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) 533 if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
534 tx->key = NULL; 534 tx->key = NULL;
535 else if (tx->sta && (key = rcu_dereference(tx->sta->key))) 535 else if (tx->sta && (key = rcu_dereference(tx->sta->ptk)))
536 tx->key = key; 536 tx->key = key;
537 else if (ieee80211_is_mgmt(hdr->frame_control) && 537 else if (ieee80211_is_mgmt(hdr->frame_control) &&
538 is_multicast_ether_addr(hdr->addr1) && 538 is_multicast_ether_addr(hdr->addr1) &&
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 37580e090a3d..2d1d4c70113c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -375,7 +375,7 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
375/* internal helpers */ 375/* internal helpers */
376int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 376int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
377 struct key_params *params, int key_idx, 377 struct key_params *params, int key_idx,
378 const u8 *mac_addr); 378 bool pairwise, const u8 *mac_addr);
379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
380 size_t ie_len, u16 reason, bool from_ap); 380 size_t ie_len, u16 reason, bool from_ap);
381void cfg80211_sme_scan_done(struct net_device *dev); 381void cfg80211_sme_scan_done(struct net_device *dev);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 8cb6e08373b9..f33fbb79437c 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -160,7 +160,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
160 */ 160 */
161 if (rdev->ops->del_key) 161 if (rdev->ops->del_key)
162 for (i = 0; i < 6; i++) 162 for (i = 0; i < 6; i++)
163 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 163 rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
164 164
165 if (wdev->current_bss) { 165 if (wdev->current_bss) {
166 cfg80211_unhold_bss(wdev->current_bss); 166 cfg80211_unhold_bss(wdev->current_bss);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0c9497170f1f..8826888cc14e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -93,6 +93,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
93 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 93 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
94 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 94 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
95 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 95 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
96 [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
96 97
97 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, 98 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
98 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, 99 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
@@ -168,7 +169,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
168 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, 169 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
169}; 170};
170 171
171/* policy for the attributes */ 172/* policy for the key attributes */
172static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { 173static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
173 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, 174 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
174 [NL80211_KEY_IDX] = { .type = NLA_U8 }, 175 [NL80211_KEY_IDX] = { .type = NLA_U8 },
@@ -176,6 +177,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
176 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 177 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
177 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, 178 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
178 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, 179 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
180 [NL80211_KEY_TYPE] = { .type = NLA_U32 },
179}; 181};
180 182
181/* ifidx get helper */ 183/* ifidx get helper */
@@ -306,6 +308,7 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
306struct key_parse { 308struct key_parse {
307 struct key_params p; 309 struct key_params p;
308 int idx; 310 int idx;
311 int type;
309 bool def, defmgmt; 312 bool def, defmgmt;
310}; 313};
311 314
@@ -336,6 +339,12 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
336 if (tb[NL80211_KEY_CIPHER]) 339 if (tb[NL80211_KEY_CIPHER])
337 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]); 340 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
338 341
342 if (tb[NL80211_KEY_TYPE]) {
343 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
344 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
345 return -EINVAL;
346 }
347
339 return 0; 348 return 0;
340} 349}
341 350
@@ -360,6 +369,12 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
360 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; 369 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
361 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; 370 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
362 371
372 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
373 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
374 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
375 return -EINVAL;
376 }
377
363 return 0; 378 return 0;
364} 379}
365 380
@@ -369,6 +384,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
369 384
370 memset(k, 0, sizeof(*k)); 385 memset(k, 0, sizeof(*k));
371 k->idx = -1; 386 k->idx = -1;
387 k->type = -1;
372 388
373 if (info->attrs[NL80211_ATTR_KEY]) 389 if (info->attrs[NL80211_ATTR_KEY])
374 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); 390 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
@@ -433,7 +449,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
433 } else if (parse.defmgmt) 449 } else if (parse.defmgmt)
434 goto error; 450 goto error;
435 err = cfg80211_validate_key_settings(rdev, &parse.p, 451 err = cfg80211_validate_key_settings(rdev, &parse.p,
436 parse.idx, NULL); 452 parse.idx, false, NULL);
437 if (err) 453 if (err)
438 goto error; 454 goto error;
439 result->params[parse.idx].cipher = parse.p.cipher; 455 result->params[parse.idx].cipher = parse.p.cipher;
@@ -516,6 +532,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
516 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 532 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
517 dev->wiphy.max_scan_ie_len); 533 dev->wiphy.max_scan_ie_len);
518 534
535 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
536 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
537
519 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, 538 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
520 sizeof(u32) * dev->wiphy.n_cipher_suites, 539 sizeof(u32) * dev->wiphy.n_cipher_suites,
521 dev->wiphy.cipher_suites); 540 dev->wiphy.cipher_suites);
@@ -1446,7 +1465,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1446 int err; 1465 int err;
1447 struct net_device *dev = info->user_ptr[1]; 1466 struct net_device *dev = info->user_ptr[1];
1448 u8 key_idx = 0; 1467 u8 key_idx = 0;
1449 u8 *mac_addr = NULL; 1468 const u8 *mac_addr = NULL;
1469 bool pairwise;
1450 struct get_key_cookie cookie = { 1470 struct get_key_cookie cookie = {
1451 .error = 0, 1471 .error = 0,
1452 }; 1472 };
@@ -1462,6 +1482,17 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1462 if (info->attrs[NL80211_ATTR_MAC]) 1482 if (info->attrs[NL80211_ATTR_MAC])
1463 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1483 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1464 1484
1485 pairwise = !!mac_addr;
1486 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
1487 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
1488 if (kt >= NUM_NL80211_KEYTYPES)
1489 return -EINVAL;
1490 if (kt != NL80211_KEYTYPE_GROUP &&
1491 kt != NL80211_KEYTYPE_PAIRWISE)
1492 return -EINVAL;
1493 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
1494 }
1495
1465 if (!rdev->ops->get_key) 1496 if (!rdev->ops->get_key)
1466 return -EOPNOTSUPP; 1497 return -EOPNOTSUPP;
1467 1498
@@ -1482,8 +1513,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1482 if (mac_addr) 1513 if (mac_addr)
1483 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 1514 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1484 1515
1485 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr, 1516 if (pairwise && mac_addr &&
1486 &cookie, get_key_callback); 1517 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
1518 return -ENOENT;
1519
1520 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
1521 mac_addr, &cookie, get_key_callback);
1487 1522
1488 if (err) 1523 if (err)
1489 goto free_msg; 1524 goto free_msg;
@@ -1553,7 +1588,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1553 int err; 1588 int err;
1554 struct net_device *dev = info->user_ptr[1]; 1589 struct net_device *dev = info->user_ptr[1];
1555 struct key_parse key; 1590 struct key_parse key;
1556 u8 *mac_addr = NULL; 1591 const u8 *mac_addr = NULL;
1557 1592
1558 err = nl80211_parse_key(info, &key); 1593 err = nl80211_parse_key(info, &key);
1559 if (err) 1594 if (err)
@@ -1565,16 +1600,31 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1565 if (info->attrs[NL80211_ATTR_MAC]) 1600 if (info->attrs[NL80211_ATTR_MAC])
1566 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1601 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1567 1602
1603 if (key.type == -1) {
1604 if (mac_addr)
1605 key.type = NL80211_KEYTYPE_PAIRWISE;
1606 else
1607 key.type = NL80211_KEYTYPE_GROUP;
1608 }
1609
1610 /* for now */
1611 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
1612 key.type != NL80211_KEYTYPE_GROUP)
1613 return -EINVAL;
1614
1568 if (!rdev->ops->add_key) 1615 if (!rdev->ops->add_key)
1569 return -EOPNOTSUPP; 1616 return -EOPNOTSUPP;
1570 1617
1571 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) 1618 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
1619 key.type == NL80211_KEYTYPE_PAIRWISE,
1620 mac_addr))
1572 return -EINVAL; 1621 return -EINVAL;
1573 1622
1574 wdev_lock(dev->ieee80211_ptr); 1623 wdev_lock(dev->ieee80211_ptr);
1575 err = nl80211_key_allowed(dev->ieee80211_ptr); 1624 err = nl80211_key_allowed(dev->ieee80211_ptr);
1576 if (!err) 1625 if (!err)
1577 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, 1626 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
1627 key.type == NL80211_KEYTYPE_PAIRWISE,
1578 mac_addr, &key.p); 1628 mac_addr, &key.p);
1579 wdev_unlock(dev->ieee80211_ptr); 1629 wdev_unlock(dev->ieee80211_ptr);
1580 1630
@@ -1596,13 +1646,32 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1596 if (info->attrs[NL80211_ATTR_MAC]) 1646 if (info->attrs[NL80211_ATTR_MAC])
1597 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1647 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1598 1648
1649 if (key.type == -1) {
1650 if (mac_addr)
1651 key.type = NL80211_KEYTYPE_PAIRWISE;
1652 else
1653 key.type = NL80211_KEYTYPE_GROUP;
1654 }
1655
1656 /* for now */
1657 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
1658 key.type != NL80211_KEYTYPE_GROUP)
1659 return -EINVAL;
1660
1599 if (!rdev->ops->del_key) 1661 if (!rdev->ops->del_key)
1600 return -EOPNOTSUPP; 1662 return -EOPNOTSUPP;
1601 1663
1602 wdev_lock(dev->ieee80211_ptr); 1664 wdev_lock(dev->ieee80211_ptr);
1603 err = nl80211_key_allowed(dev->ieee80211_ptr); 1665 err = nl80211_key_allowed(dev->ieee80211_ptr);
1666
1667 if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr &&
1668 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
1669 err = -ENOENT;
1670
1604 if (!err) 1671 if (!err)
1605 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); 1672 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx,
1673 key.type == NL80211_KEYTYPE_PAIRWISE,
1674 mac_addr);
1606 1675
1607#ifdef CONFIG_CFG80211_WEXT 1676#ifdef CONFIG_CFG80211_WEXT
1608 if (!err) { 1677 if (!err) {
@@ -3212,6 +3281,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3212 return err; 3281 return err;
3213 3282
3214 if (key.idx >= 0) { 3283 if (key.idx >= 0) {
3284 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
3285 return -EINVAL;
3215 if (!key.p.key || !key.p.key_len) 3286 if (!key.p.key || !key.p.key_len)
3216 return -EINVAL; 3287 return -EINVAL;
3217 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 || 3288 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f161b9844542..e17b0bee6bdc 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -698,7 +698,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
698 */ 698 */
699 if (rdev->ops->del_key) 699 if (rdev->ops->del_key)
700 for (i = 0; i < 6; i++) 700 for (i = 0; i < 6; i++)
701 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 701 rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
702 702
703#ifdef CONFIG_CFG80211_WEXT 703#ifdef CONFIG_CFG80211_WEXT
704 memset(&wrqu, 0, sizeof(wrqu)); 704 memset(&wrqu, 0, sizeof(wrqu));
diff --git a/net/wireless/util.c b/net/wireless/util.c
index fb5448f7d55a..76120aeda57d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -144,19 +144,25 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
144 144
145int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 145int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
146 struct key_params *params, int key_idx, 146 struct key_params *params, int key_idx,
147 const u8 *mac_addr) 147 bool pairwise, const u8 *mac_addr)
148{ 148{
149 int i; 149 int i;
150 150
151 if (key_idx > 5) 151 if (key_idx > 5)
152 return -EINVAL; 152 return -EINVAL;
153 153
154 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
155 return -EINVAL;
156
157 if (pairwise && !mac_addr)
158 return -EINVAL;
159
154 /* 160 /*
155 * Disallow pairwise keys with non-zero index unless it's WEP 161 * Disallow pairwise keys with non-zero index unless it's WEP
156 * (because current deployments use pairwise WEP keys with 162 * (because current deployments use pairwise WEP keys with
157 * non-zero indizes but 802.11i clearly specifies to use zero) 163 * non-zero indizes but 802.11i clearly specifies to use zero)
158 */ 164 */
159 if (mac_addr && key_idx && 165 if (pairwise && key_idx &&
160 params->cipher != WLAN_CIPHER_SUITE_WEP40 && 166 params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
161 params->cipher != WLAN_CIPHER_SUITE_WEP104) 167 params->cipher != WLAN_CIPHER_SUITE_WEP104)
162 return -EINVAL; 168 return -EINVAL;
@@ -677,7 +683,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
677 for (i = 0; i < 6; i++) { 683 for (i = 0; i < 6; i++) {
678 if (!wdev->connect_keys->params[i].cipher) 684 if (!wdev->connect_keys->params[i].cipher)
679 continue; 685 continue;
680 if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL, 686 if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
681 &wdev->connect_keys->params[i])) { 687 &wdev->connect_keys->params[i])) {
682 printk(KERN_ERR "%s: failed to set key %d\n", 688 printk(KERN_ERR "%s: failed to set key %d\n",
683 dev->name, i); 689 dev->name, i);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 7e5c3a45f811..6002265289c6 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -432,14 +432,17 @@ int cfg80211_wext_giwretry(struct net_device *dev,
432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
433 433
434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
435 struct net_device *dev, const u8 *addr, 435 struct net_device *dev, bool pairwise,
436 bool remove, bool tx_key, int idx, 436 const u8 *addr, bool remove, bool tx_key,
437 struct key_params *params) 437 int idx, struct key_params *params)
438{ 438{
439 struct wireless_dev *wdev = dev->ieee80211_ptr; 439 struct wireless_dev *wdev = dev->ieee80211_ptr;
440 int err, i; 440 int err, i;
441 bool rejoin = false; 441 bool rejoin = false;
442 442
443 if (pairwise && !addr)
444 return -EINVAL;
445
443 if (!wdev->wext.keys) { 446 if (!wdev->wext.keys) {
444 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), 447 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
445 GFP_KERNEL); 448 GFP_KERNEL);
@@ -478,7 +481,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
478 __cfg80211_leave_ibss(rdev, wdev->netdev, true); 481 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
479 rejoin = true; 482 rejoin = true;
480 } 483 }
481 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 484
485 if (!pairwise && addr &&
486 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
487 err = -ENOENT;
488 else
489 err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
490 pairwise, addr);
482 } 491 }
483 wdev->wext.connect.privacy = false; 492 wdev->wext.connect.privacy = false;
484 /* 493 /*
@@ -507,12 +516,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
507 if (addr) 516 if (addr)
508 tx_key = false; 517 tx_key = false;
509 518
510 if (cfg80211_validate_key_settings(rdev, params, idx, addr)) 519 if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
511 return -EINVAL; 520 return -EINVAL;
512 521
513 err = 0; 522 err = 0;
514 if (wdev->current_bss) 523 if (wdev->current_bss)
515 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 524 err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
525 pairwise, addr, params);
516 if (err) 526 if (err)
517 return err; 527 return err;
518 528
@@ -563,17 +573,17 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
563} 573}
564 574
565static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 575static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
566 struct net_device *dev, const u8 *addr, 576 struct net_device *dev, bool pairwise,
567 bool remove, bool tx_key, int idx, 577 const u8 *addr, bool remove, bool tx_key,
568 struct key_params *params) 578 int idx, struct key_params *params)
569{ 579{
570 int err; 580 int err;
571 581
572 /* devlist mutex needed for possible IBSS re-join */ 582 /* devlist mutex needed for possible IBSS re-join */
573 mutex_lock(&rdev->devlist_mtx); 583 mutex_lock(&rdev->devlist_mtx);
574 wdev_lock(dev->ieee80211_ptr); 584 wdev_lock(dev->ieee80211_ptr);
575 err = __cfg80211_set_encryption(rdev, dev, addr, remove, 585 err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
576 tx_key, idx, params); 586 remove, tx_key, idx, params);
577 wdev_unlock(dev->ieee80211_ptr); 587 wdev_unlock(dev->ieee80211_ptr);
578 mutex_unlock(&rdev->devlist_mtx); 588 mutex_unlock(&rdev->devlist_mtx);
579 589
@@ -635,7 +645,7 @@ int cfg80211_wext_siwencode(struct net_device *dev,
635 else if (!remove) 645 else if (!remove)
636 return -EINVAL; 646 return -EINVAL;
637 647
638 return cfg80211_set_encryption(rdev, dev, NULL, remove, 648 return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
639 wdev->wext.default_key == -1, 649 wdev->wext.default_key == -1,
640 idx, &params); 650 idx, &params);
641} 651}
@@ -725,7 +735,9 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
725 } 735 }
726 736
727 return cfg80211_set_encryption( 737 return cfg80211_set_encryption(
728 rdev, dev, addr, remove, 738 rdev, dev,
739 !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
740 addr, remove,
729 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 741 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
730 idx, &params); 742 idx, &params);
731} 743}