Commit fffd0934b9390f34bec45762192b7edd3b12b4b5

Authored by Johannes Berg
Committed by John W. Linville
1 parent b9454e83ca

cfg80211: rework key operation

This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.

In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.

Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 17 changed files with 554 additions and 161 deletions Side-by-side Diff

include/linux/nl80211.h
... ... @@ -569,6 +569,9 @@
569 569 *
570 570 * @NL80211_ATTR_KEY: key information in a nested attribute with
571 571 * %NL80211_KEY_* sub-attributes
  572 + * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
  573 + * and join_ibss(), key information is in a nested attribute each
  574 + * with %NL80211_KEY_* sub-attributes
572 575 *
573 576 * @NL80211_ATTR_MAX: highest attribute number currently defined
574 577 * @__NL80211_ATTR_AFTER_LAST: internal use
... ... @@ -696,6 +699,7 @@
696 699 NL80211_ATTR_PREV_BSSID,
697 700  
698 701 NL80211_ATTR_KEY,
  702 + NL80211_ATTR_KEYS,
699 703  
700 704 /* add attributes here, update the policy in nl80211.c */
701 705  
... ... @@ -726,6 +730,7 @@
726 730 #define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
727 731 #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
728 732 #define NL80211_ATTR_KEY NL80211_ATTR_KEY
  733 +#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
729 734  
730 735 #define NL80211_MAX_SUPP_RATES 32
731 736 #define NL80211_MAX_SUPP_REG_RULES 32
include/net/cfg80211.h
... ... @@ -647,12 +647,17 @@
647 647 * @auth_type: Authentication type (algorithm)
648 648 * @ie: Extra IEs to add to Authentication frame or %NULL
649 649 * @ie_len: Length of ie buffer in octets
  650 + * @key_len: length of WEP key for shared key authentication
  651 + * @key_idx: index of WEP key for shared key authentication
  652 + * @key: WEP key for shared key authentication
650 653 */
651 654 struct cfg80211_auth_request {
652 655 struct cfg80211_bss *bss;
653 656 const u8 *ie;
654 657 size_t ie_len;
655 658 enum nl80211_auth_type auth_type;
  659 + const u8 *key;
  660 + u8 key_len, key_idx;
656 661 };
657 662  
658 663 /**
... ... @@ -727,6 +732,8 @@
727 732 * @ie: information element(s) to include in the beacon
728 733 * @ie_len: length of that
729 734 * @beacon_interval: beacon interval to use
  735 + * @privacy: this is a protected network, keys will be configured
  736 + * after joining
730 737 */
731 738 struct cfg80211_ibss_params {
732 739 u8 *ssid;
... ... @@ -736,6 +743,7 @@
736 743 u8 ssid_len, ie_len;
737 744 u16 beacon_interval;
738 745 bool channel_fixed;
  746 + bool privacy;
739 747 };
740 748  
741 749 /**
... ... @@ -755,6 +763,9 @@
755 763 * @assoc_ie_len: Length of assoc_ie in octets
756 764 * @privacy: indicates whether privacy-enabled APs should be used
757 765 * @crypto: crypto settings
  766 + * @key_len: length of WEP key for shared key authentication
  767 + * @key_idx: index of WEP key for shared key authentication
  768 + * @key: WEP key for shared key authentication
758 769 */
759 770 struct cfg80211_connect_params {
760 771 struct ieee80211_channel *channel;
... ... @@ -766,6 +777,8 @@
766 777 size_t ie_len;
767 778 bool privacy;
768 779 struct cfg80211_crypto_settings crypto;
  780 + const u8 *key;
  781 + u8 key_len, key_idx;
769 782 };
770 783  
771 784 /**
772 785  
... ... @@ -1223,9 +1236,10 @@
1223 1236 */
1224 1237 extern void wiphy_free(struct wiphy *wiphy);
1225 1238  
1226   -/* internal struct */
  1239 +/* internal structs */
1227 1240 struct cfg80211_conn;
1228 1241 struct cfg80211_internal_bss;
  1242 +struct cfg80211_cached_keys;
1229 1243  
1230 1244 #define MAX_AUTH_BSSES 4
1231 1245  
... ... @@ -1267,6 +1281,7 @@
1267 1281 CFG80211_SME_CONNECTED,
1268 1282 } sme_state;
1269 1283 struct cfg80211_conn *conn;
  1284 + struct cfg80211_cached_keys *connect_keys;
1270 1285  
1271 1286 struct list_head event_list;
1272 1287 spinlock_t event_lock;
... ... @@ -1280,6 +1295,7 @@
1280 1295 struct {
1281 1296 struct cfg80211_ibss_params ibss;
1282 1297 struct cfg80211_connect_params connect;
  1298 + struct cfg80211_cached_keys *keys;
1283 1299 u8 *ie;
1284 1300 size_t ie_len;
1285 1301 u8 bssid[ETH_ALEN];
... ... @@ -57,7 +57,7 @@
57 57 */
58 58 if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1)
59 59 ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0,
60   - sdata->u.ibss.bssid, 0);
  60 + sdata->u.ibss.bssid, NULL, 0, 0);
61 61 }
62 62  
63 63 static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
... ... @@ -494,7 +494,7 @@
494 494  
495 495 capability = WLAN_CAPABILITY_IBSS;
496 496  
497   - if (sdata->default_key)
  497 + if (ifibss->privacy)
498 498 capability |= WLAN_CAPABILITY_PRIVACY;
499 499 else
500 500 sdata->drop_unencrypted = 0;
501 501  
... ... @@ -524,9 +524,8 @@
524 524 return;
525 525  
526 526 capability = WLAN_CAPABILITY_IBSS;
527   - if (sdata->default_key)
  527 + if (ifibss->privacy)
528 528 capability |= WLAN_CAPABILITY_PRIVACY;
529   -
530 529 if (ifibss->fixed_bssid)
531 530 bssid = ifibss->bssid;
532 531 if (ifibss->fixed_channel)
... ... @@ -871,6 +870,8 @@
871 870 sdata->u.ibss.fixed_bssid = true;
872 871 } else
873 872 sdata->u.ibss.fixed_bssid = false;
  873 +
  874 + sdata->u.ibss.privacy = params->privacy;
874 875  
875 876 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
876 877  
net/mac80211/ieee80211_i.h
... ... @@ -247,6 +247,9 @@
247 247  
248 248 int tries;
249 249  
  250 + u8 key[WLAN_KEY_LEN_WEP104];
  251 + u8 key_len, key_idx;
  252 +
250 253 /* must be last */
251 254 u8 ie[0]; /* for auth or assoc frame, not probe */
252 255 };
... ... @@ -321,6 +324,7 @@
321 324  
322 325 bool fixed_bssid;
323 326 bool fixed_channel;
  327 + bool privacy;
324 328  
325 329 u8 bssid[ETH_ALEN];
326 330 u8 ssid[IEEE80211_MAX_SSID_LEN];
... ... @@ -1093,8 +1097,8 @@
1093 1097  
1094 1098 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1095 1099 u16 transaction, u16 auth_alg,
1096   - u8 *extra, size_t extra_len,
1097   - const u8 *bssid, int encrypt);
  1100 + u8 *extra, size_t extra_len, const u8 *bssid,
  1101 + const u8 *key, u8 key_len, u8 key_idx);
1098 1102 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1099 1103 const u8 *ie, size_t ie_len);
1100 1104 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
... ... @@ -954,7 +954,7 @@
954 954 sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
955 955  
956 956 ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
957   - wk->bss->cbss.bssid, 0);
  957 + wk->bss->cbss.bssid, NULL, 0, 0);
958 958 wk->auth_transaction = 2;
959 959  
960 960 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
... ... @@ -1176,7 +1176,8 @@
1176 1176 return;
1177 1177 ieee80211_send_auth(sdata, 3, wk->auth_alg,
1178 1178 elems.challenge - 2, elems.challenge_len + 2,
1179   - wk->bss->cbss.bssid, 1);
  1179 + wk->bss->cbss.bssid,
  1180 + wk->key, wk->key_len, wk->key_idx);
1180 1181 wk->auth_transaction = 4;
1181 1182 }
1182 1183  
... ... @@ -2173,6 +2174,12 @@
2173 2174 if (req->ie && req->ie_len) {
2174 2175 memcpy(wk->ie, req->ie, req->ie_len);
2175 2176 wk->ie_len = req->ie_len;
  2177 + }
  2178 +
  2179 + if (req->key && req->key_len) {
  2180 + wk->key_len = req->key_len;
  2181 + wk->key_idx = req->key_idx;
  2182 + memcpy(wk->key, req->key, req->key_len);
2176 2183 }
2177 2184  
2178 2185 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
... ... @@ -31,6 +31,7 @@
31 31 #include "mesh.h"
32 32 #include "wme.h"
33 33 #include "led.h"
  34 +#include "wep.h"
34 35  
35 36 /* privid for wiphys to determine whether they belong to us or not */
36 37 void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
37 38  
... ... @@ -804,12 +805,13 @@
804 805  
805 806 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
806 807 u16 transaction, u16 auth_alg,
807   - u8 *extra, size_t extra_len,
808   - const u8 *bssid, int encrypt)
  808 + u8 *extra, size_t extra_len, const u8 *bssid,
  809 + const u8 *key, u8 key_len, u8 key_idx)
809 810 {
810 811 struct ieee80211_local *local = sdata->local;
811 812 struct sk_buff *skb;
812 813 struct ieee80211_mgmt *mgmt;
  814 + int err;
813 815  
814 816 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
815 817 sizeof(*mgmt) + 6 + extra_len);
... ... @@ -824,8 +826,6 @@
824 826 memset(mgmt, 0, 24 + 6);
825 827 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
826 828 IEEE80211_STYPE_AUTH);
827   - if (encrypt)
828   - mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
829 829 memcpy(mgmt->da, bssid, ETH_ALEN);
830 830 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
831 831 memcpy(mgmt->bssid, bssid, ETH_ALEN);
... ... @@ -835,7 +835,13 @@
835 835 if (extra)
836 836 memcpy(skb_put(skb, extra_len), extra, extra_len);
837 837  
838   - ieee80211_tx_skb(sdata, skb, encrypt);
  838 + if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
  839 + mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
  840 + err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
  841 + WARN_ON(err);
  842 + }
  843 +
  844 + ieee80211_tx_skb(sdata, skb, 0);
839 845 }
840 846  
841 847 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
... ... @@ -144,9 +144,9 @@
144 144 *
145 145 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
146 146 */
147   -static int ieee80211_wep_encrypt(struct ieee80211_local *local,
148   - struct sk_buff *skb,
149   - const u8 *key, int keylen, int keyidx)
  147 +int ieee80211_wep_encrypt(struct ieee80211_local *local,
  148 + struct sk_buff *skb,
  149 + const u8 *key, int keylen, int keyidx)
150 150 {
151 151 u8 *iv;
152 152 size_t len;
... ... @@ -20,6 +20,9 @@
20 20 void ieee80211_wep_free(struct ieee80211_local *local);
21 21 void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
22 22 size_t klen, u8 *data, size_t data_len);
  23 +int ieee80211_wep_encrypt(struct ieee80211_local *local,
  24 + struct sk_buff *skb,
  25 + const u8 *key, int keylen, int keyidx);
23 26 int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
24 27 size_t klen, u8 *data, size_t data_len);
25 28 bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
... ... @@ -666,14 +666,10 @@
666 666 wdev_lock(wdev);
667 667 switch (wdev->iftype) {
668 668 case NL80211_IFTYPE_ADHOC:
669   - if (wdev->wext.ibss.ssid_len)
670   - __cfg80211_join_ibss(rdev, dev,
671   - &wdev->wext.ibss);
  669 + cfg80211_ibss_wext_join(rdev, wdev);
672 670 break;
673 671 case NL80211_IFTYPE_STATION:
674   - if (wdev->wext.connect.ssid_len)
675   - __cfg80211_connect(rdev, dev,
676   - &wdev->wext.connect);
  672 + cfg80211_mgd_wext_connect(rdev, wdev);
677 673 break;
678 674 default:
679 675 break;
... ... @@ -690,6 +686,9 @@
690 686 }
691 687 mutex_unlock(&rdev->devlist_mtx);
692 688 mutex_destroy(&wdev->mtx);
  689 +#ifdef CONFIG_WIRELESS_EXT
  690 + kfree(wdev->wext.keys);
  691 +#endif
693 692 break;
694 693 case NETDEV_PRE_UP:
695 694 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
... ... @@ -238,7 +238,13 @@
238 238 };
239 239 };
240 240  
  241 +struct cfg80211_cached_keys {
  242 + struct key_params params[6];
  243 + u8 data[6][WLAN_MAX_KEY_LEN];
  244 + int def, defmgmt;
  245 +};
241 246  
  247 +
242 248 /* free object */
243 249 extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
244 250  
245 251  
246 252  
... ... @@ -256,14 +262,18 @@
256 262 /* IBSS */
257 263 int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
258 264 struct net_device *dev,
259   - struct cfg80211_ibss_params *params);
  265 + struct cfg80211_ibss_params *params,
  266 + struct cfg80211_cached_keys *connkeys);
260 267 int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
261 268 struct net_device *dev,
262   - struct cfg80211_ibss_params *params);
  269 + struct cfg80211_ibss_params *params,
  270 + struct cfg80211_cached_keys *connkeys);
263 271 void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
264 272 int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
265 273 struct net_device *dev, bool nowext);
266 274 void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
  275 +int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
  276 + struct wireless_dev *wdev);
267 277  
268 278 /* MLME */
269 279 int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
270 280  
... ... @@ -272,12 +282,14 @@
272 282 enum nl80211_auth_type auth_type,
273 283 const u8 *bssid,
274 284 const u8 *ssid, int ssid_len,
275   - const u8 *ie, int ie_len);
  285 + const u8 *ie, int ie_len,
  286 + const u8 *key, int key_len, int key_idx);
276 287 int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
277 288 struct net_device *dev, struct ieee80211_channel *chan,
278 289 enum nl80211_auth_type auth_type, const u8 *bssid,
279 290 const u8 *ssid, int ssid_len,
280   - const u8 *ie, int ie_len);
  291 + const u8 *ie, int ie_len,
  292 + const u8 *key, int key_len, int key_idx);
281 293 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
282 294 struct net_device *dev,
283 295 struct ieee80211_channel *chan,
284 296  
... ... @@ -310,10 +322,12 @@
310 322 /* SME */
311 323 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
312 324 struct net_device *dev,
313   - struct cfg80211_connect_params *connect);
  325 + struct cfg80211_connect_params *connect,
  326 + struct cfg80211_cached_keys *connkeys);
314 327 int cfg80211_connect(struct cfg80211_registered_device *rdev,
315 328 struct net_device *dev,
316   - struct cfg80211_connect_params *connect);
  329 + struct cfg80211_connect_params *connect,
  330 + struct cfg80211_cached_keys *connkeys);
317 331 int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
318 332 struct net_device *dev, u16 reason,
319 333 bool wextev);
320 334  
... ... @@ -323,11 +337,14 @@
323 337 void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
324 338 const u8 *req_ie, size_t req_ie_len,
325 339 const u8 *resp_ie, size_t resp_ie_len);
  340 +int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
  341 + struct wireless_dev *wdev);
326 342  
327 343 void cfg80211_conn_work(struct work_struct *work);
328 344  
329 345 /* internal helpers */
330   -int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
  346 +int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
  347 + struct key_params *params, int key_idx,
331 348 const u8 *mac_addr);
332 349 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
333 350 size_t ie_len, u16 reason, bool from_ap);
... ... @@ -335,6 +352,7 @@
335 352 void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
336 353 void cfg80211_sme_disassoc(struct net_device *dev, int idx);
337 354 void __cfg80211_scan_done(struct work_struct *wk);
  355 +void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
338 356  
339 357 #endif /* __NET_WIRELESS_CORE_H */
... ... @@ -39,6 +39,8 @@
39 39 cfg80211_hold_bss(bss_from_pub(bss));
40 40 wdev->current_bss = bss_from_pub(bss);
41 41  
  42 + cfg80211_upload_connect_keys(wdev);
  43 +
42 44 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
43 45 GFP_KERNEL);
44 46 #ifdef CONFIG_WIRELESS_EXT
... ... @@ -71,7 +73,8 @@
71 73  
72 74 int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
73 75 struct net_device *dev,
74   - struct cfg80211_ibss_params *params)
  76 + struct cfg80211_ibss_params *params,
  77 + struct cfg80211_cached_keys *connkeys)
75 78 {
76 79 struct wireless_dev *wdev = dev->ieee80211_ptr;
77 80 int err;
78 81  
79 82  
... ... @@ -81,13 +84,18 @@
81 84 if (wdev->ssid_len)
82 85 return -EALREADY;
83 86  
  87 + if (WARN_ON(wdev->connect_keys))
  88 + kfree(wdev->connect_keys);
  89 + wdev->connect_keys = connkeys;
  90 +
84 91 #ifdef CONFIG_WIRELESS_EXT
85 92 wdev->wext.ibss.channel = params->channel;
86 93 #endif
87 94 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
88   -
89   - if (err)
  95 + if (err) {
  96 + wdev->connect_keys = NULL;
90 97 return err;
  98 + }
91 99  
92 100 memcpy(wdev->ssid, params->ssid, params->ssid_len);
93 101 wdev->ssid_len = params->ssid_len;
94 102  
... ... @@ -97,13 +105,14 @@
97 105  
98 106 int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
99 107 struct net_device *dev,
100   - struct cfg80211_ibss_params *params)
  108 + struct cfg80211_ibss_params *params,
  109 + struct cfg80211_cached_keys *connkeys)
101 110 {
102 111 struct wireless_dev *wdev = dev->ieee80211_ptr;
103 112 int err;
104 113  
105 114 wdev_lock(wdev);
106   - err = __cfg80211_join_ibss(rdev, dev, params);
  115 + err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
107 116 wdev_unlock(wdev);
108 117  
109 118 return err;
110 119  
... ... @@ -112,9 +121,22 @@
112 121 static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
113 122 {
114 123 struct wireless_dev *wdev = dev->ieee80211_ptr;
  124 + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
  125 + int i;
115 126  
116 127 ASSERT_WDEV_LOCK(wdev);
117 128  
  129 + kfree(wdev->connect_keys);
  130 + wdev->connect_keys = NULL;
  131 +
  132 + /*
  133 + * Delete all the keys ... pairwise keys can't really
  134 + * exist any more anyway, but default keys might.
  135 + */
  136 + if (rdev->ops->del_key)
  137 + for (i = 0; i < 6; i++)
  138 + rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
  139 +
118 140 if (wdev->current_bss) {
119 141 cfg80211_unhold_bss(wdev->current_bss);
120 142 cfg80211_put_bss(&wdev->current_bss->pub);
121 143  
122 144  
123 145  
... ... @@ -172,12 +194,15 @@
172 194 }
173 195  
174 196 #ifdef CONFIG_WIRELESS_EXT
175   -static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
176   - struct wireless_dev *wdev)
  197 +int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
  198 + struct wireless_dev *wdev)
177 199 {
  200 + struct cfg80211_cached_keys *ck = NULL;
178 201 enum ieee80211_band band;
179   - int i;
  202 + int i, err;
180 203  
  204 + ASSERT_WDEV_LOCK(wdev);
  205 +
181 206 if (!wdev->wext.ibss.beacon_interval)
182 207 wdev->wext.ibss.beacon_interval = 100;
183 208  
... ... @@ -216,8 +241,24 @@
216 241 if (!netif_running(wdev->netdev))
217 242 return 0;
218 243  
219   - return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy),
220   - wdev->netdev, &wdev->wext.ibss);
  244 + if (wdev->wext.keys)
  245 + wdev->wext.keys->def = wdev->wext.default_key;
  246 +
  247 + wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
  248 +
  249 + if (wdev->wext.keys) {
  250 + ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
  251 + if (!ck)
  252 + return -ENOMEM;
  253 + for (i = 0; i < 6; i++)
  254 + ck->params[i].key = ck->data[i];
  255 + }
  256 + err = __cfg80211_join_ibss(rdev, wdev->netdev,
  257 + &wdev->wext.ibss, ck);
  258 + if (err)
  259 + kfree(ck);
  260 +
  261 + return err;
221 262 }
222 263  
223 264 int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
... ... @@ -265,7 +306,11 @@
265 306 wdev->wext.ibss.channel_fixed = false;
266 307 }
267 308  
268   - return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
  309 + wdev_lock(wdev);
  310 + err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
  311 + wdev_unlock(wdev);
  312 +
  313 + return err;
269 314 }
270 315 /* temporary symbol - mark GPL - in the future the handler won't be */
271 316 EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq);
... ... @@ -333,7 +378,11 @@
333 378 memcpy(wdev->wext.ibss.ssid, ssid, len);
334 379 wdev->wext.ibss.ssid_len = len;
335 380  
336   - return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
  381 + wdev_lock(wdev);
  382 + err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
  383 + wdev_unlock(wdev);
  384 +
  385 + return err;
337 386 }
338 387 /* temporary symbol - mark GPL - in the future the handler won't be */
339 388 EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid);
... ... @@ -414,7 +463,11 @@
414 463 } else
415 464 wdev->wext.ibss.bssid = NULL;
416 465  
417   - return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
  466 + wdev_lock(wdev);
  467 + err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
  468 + wdev_unlock(wdev);
  469 +
  470 + return err;
418 471 }
419 472 /* temporary symbol - mark GPL - in the future the handler won't be */
420 473 EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap);
... ... @@ -328,7 +328,8 @@
328 328 enum nl80211_auth_type auth_type,
329 329 const u8 *bssid,
330 330 const u8 *ssid, int ssid_len,
331   - const u8 *ie, int ie_len)
  331 + const u8 *ie, int ie_len,
  332 + const u8 *key, int key_len, int key_idx)
332 333 {
333 334 struct wireless_dev *wdev = dev->ieee80211_ptr;
334 335 struct cfg80211_auth_request req;
... ... @@ -337,6 +338,10 @@
337 338  
338 339 ASSERT_WDEV_LOCK(wdev);
339 340  
  341 + if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
  342 + if (!key || !key_len || key_idx < 0 || key_idx > 4)
  343 + return -EINVAL;
  344 +
340 345 if (wdev->current_bss &&
341 346 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
342 347 return -EALREADY;
... ... @@ -359,6 +364,9 @@
359 364 req.auth_type = auth_type;
360 365 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
361 366 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  367 + req.key = key;
  368 + req.key_len = key_len;
  369 + req.key_idx = key_idx;
362 370 if (!req.bss)
363 371 return -ENOENT;
364 372  
365 373  
... ... @@ -396,13 +404,15 @@
396 404 struct net_device *dev, struct ieee80211_channel *chan,
397 405 enum nl80211_auth_type auth_type, const u8 *bssid,
398 406 const u8 *ssid, int ssid_len,
399   - const u8 *ie, int ie_len)
  407 + const u8 *ie, int ie_len,
  408 + const u8 *key, int key_len, int key_idx)
400 409 {
401 410 int err;
402 411  
403 412 wdev_lock(dev->ieee80211_ptr);
404 413 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
405   - ssid, ssid_len, ie, ie_len);
  414 + ssid, ssid_len, ie, ie_len,
  415 + key, key_len, key_idx);
406 416 wdev_unlock(dev->ieee80211_ptr);
407 417  
408 418 return err;
net/wireless/nl80211.c
... ... @@ -138,8 +138,7 @@
138 138 /* policy for the attributes */
139 139 static struct nla_policy
140 140 nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
141   - [NL80211_KEY_DATA] = { .type = NLA_BINARY,
142   - .len = WLAN_MAX_KEY_LEN },
  141 + [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
143 142 [NL80211_KEY_IDX] = { .type = NLA_U8 },
144 143 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
145 144 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
... ... @@ -305,6 +304,83 @@
305 304 return 0;
306 305 }
307 306  
  307 +static struct cfg80211_cached_keys *
  308 +nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
  309 + struct nlattr *keys)
  310 +{
  311 + struct key_parse parse;
  312 + struct nlattr *key;
  313 + struct cfg80211_cached_keys *result;
  314 + int rem, err, def = 0;
  315 +
  316 + result = kzalloc(sizeof(*result), GFP_KERNEL);
  317 + if (!result)
  318 + return ERR_PTR(-ENOMEM);
  319 +
  320 + result->def = -1;
  321 + result->defmgmt = -1;
  322 +
  323 + nla_for_each_nested(key, keys, rem) {
  324 + memset(&parse, 0, sizeof(parse));
  325 + parse.idx = -1;
  326 +
  327 + err = nl80211_parse_key_new(key, &parse);
  328 + if (err)
  329 + goto error;
  330 + err = -EINVAL;
  331 + if (!parse.p.key)
  332 + goto error;
  333 + if (parse.idx < 0 || parse.idx > 4)
  334 + goto error;
  335 + if (parse.def) {
  336 + if (def)
  337 + goto error;
  338 + def = 1;
  339 + result->def = parse.idx;
  340 + } else if (parse.defmgmt)
  341 + goto error;
  342 + err = cfg80211_validate_key_settings(rdev, &parse.p,
  343 + parse.idx, NULL);
  344 + if (err)
  345 + goto error;
  346 + result->params[parse.idx].cipher = parse.p.cipher;
  347 + result->params[parse.idx].key_len = parse.p.key_len;
  348 + result->params[parse.idx].key = result->data[parse.idx];
  349 + memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
  350 + }
  351 +
  352 + return result;
  353 + error:
  354 + kfree(result);
  355 + return ERR_PTR(err);
  356 +}
  357 +
  358 +static int nl80211_key_allowed(struct wireless_dev *wdev)
  359 +{
  360 + ASSERT_WDEV_LOCK(wdev);
  361 +
  362 + if (!netif_running(wdev->netdev))
  363 + return -ENETDOWN;
  364 +
  365 + switch (wdev->iftype) {
  366 + case NL80211_IFTYPE_AP:
  367 + case NL80211_IFTYPE_AP_VLAN:
  368 + break;
  369 + case NL80211_IFTYPE_ADHOC:
  370 + if (!wdev->current_bss)
  371 + return -ENOLINK;
  372 + break;
  373 + case NL80211_IFTYPE_STATION:
  374 + if (wdev->sme_state != CFG80211_SME_CONNECTED)
  375 + return -ENOLINK;
  376 + break;
  377 + default:
  378 + return -EINVAL;
  379 + }
  380 +
  381 + return 0;
  382 +}
  383 +
308 384 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
309 385 struct cfg80211_registered_device *dev)
310 386 {
... ... @@ -1212,7 +1288,11 @@
1212 1288 goto out;
1213 1289 }
1214 1290  
1215   - err = func(&rdev->wiphy, dev, key.idx);
  1291 + wdev_lock(dev->ieee80211_ptr);
  1292 + err = nl80211_key_allowed(dev->ieee80211_ptr);
  1293 + if (!err)
  1294 + err = func(&rdev->wiphy, dev, key.idx);
  1295 +
1216 1296 #ifdef CONFIG_WIRELESS_EXT
1217 1297 if (!err) {
1218 1298 if (func == rdev->ops->set_default_key)
... ... @@ -1221,6 +1301,7 @@
1221 1301 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
1222 1302 }
1223 1303 #endif
  1304 + wdev_unlock(dev->ieee80211_ptr);
1224 1305  
1225 1306 out:
1226 1307 cfg80211_unlock_rdev(rdev);
... ... @@ -1235,7 +1316,7 @@
1235 1316 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1236 1317 {
1237 1318 struct cfg80211_registered_device *rdev;
1238   - int err, i;
  1319 + int err;
1239 1320 struct net_device *dev;
1240 1321 struct key_parse key;
1241 1322 u8 *mac_addr = NULL;
1242 1323  
1243 1324  
1244 1325  
... ... @@ -1250,29 +1331,28 @@
1250 1331 if (info->attrs[NL80211_ATTR_MAC])
1251 1332 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1252 1333  
1253   - if (cfg80211_validate_key_settings(&key.p, key.idx, mac_addr))
1254   - return -EINVAL;
1255   -
1256 1334 rtnl_lock();
1257 1335  
1258 1336 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
1259 1337 if (err)
1260 1338 goto unlock_rtnl;
1261 1339  
1262   - for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
1263   - if (key.p.cipher == rdev->wiphy.cipher_suites[i])
1264   - break;
1265   - if (i == rdev->wiphy.n_cipher_suites) {
1266   - err = -EINVAL;
  1340 + if (!rdev->ops->add_key) {
  1341 + err = -EOPNOTSUPP;
1267 1342 goto out;
1268 1343 }
1269 1344  
1270   - if (!rdev->ops->add_key) {
1271   - err = -EOPNOTSUPP;
  1345 + if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) {
  1346 + err = -EINVAL;
1272 1347 goto out;
1273 1348 }
1274 1349  
1275   - err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, mac_addr, &key.p);
  1350 + wdev_lock(dev->ieee80211_ptr);
  1351 + err = nl80211_key_allowed(dev->ieee80211_ptr);
  1352 + if (!err)
  1353 + err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
  1354 + mac_addr, &key.p);
  1355 + wdev_unlock(dev->ieee80211_ptr);
1276 1356  
1277 1357 out:
1278 1358 cfg80211_unlock_rdev(rdev);
... ... @@ -1309,7 +1389,10 @@
1309 1389 goto out;
1310 1390 }
1311 1391  
1312   - err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
  1392 + wdev_lock(dev->ieee80211_ptr);
  1393 + err = nl80211_key_allowed(dev->ieee80211_ptr);
  1394 + if (!err)
  1395 + err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
1313 1396  
1314 1397 #ifdef CONFIG_WIRELESS_EXT
1315 1398 if (!err) {
... ... @@ -1319,6 +1402,7 @@
1319 1402 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
1320 1403 }
1321 1404 #endif
  1405 + wdev_unlock(dev->ieee80211_ptr);
1322 1406  
1323 1407 out:
1324 1408 cfg80211_unlock_rdev(rdev);
... ... @@ -3159,6 +3243,7 @@
3159 3243 const u8 *bssid, *ssid, *ie = NULL;
3160 3244 int err, ssid_len, ie_len = 0;
3161 3245 enum nl80211_auth_type auth_type;
  3246 + struct key_parse key;
3162 3247  
3163 3248 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3164 3249 return -EINVAL;
... ... @@ -3175,6 +3260,25 @@
3175 3260 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
3176 3261 return -EINVAL;
3177 3262  
  3263 + err = nl80211_parse_key(info, &key);
  3264 + if (err)
  3265 + return err;
  3266 +
  3267 + if (key.idx >= 0) {
  3268 + if (!key.p.key || !key.p.key_len)
  3269 + return -EINVAL;
  3270 + if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
  3271 + key.p.key_len != WLAN_KEY_LEN_WEP40) &&
  3272 + (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
  3273 + key.p.key_len != WLAN_KEY_LEN_WEP104))
  3274 + return -EINVAL;
  3275 + if (key.idx > 4)
  3276 + return -EINVAL;
  3277 + } else {
  3278 + key.p.key_len = 0;
  3279 + key.p.key = NULL;
  3280 + }
  3281 +
3178 3282 rtnl_lock();
3179 3283  
3180 3284 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
... ... @@ -3219,7 +3323,8 @@
3219 3323 }
3220 3324  
3221 3325 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3222   - ssid, ssid_len, ie, ie_len);
  3326 + ssid, ssid_len, ie, ie_len,
  3327 + key.p.key, key.p.key_len, key.idx);
3223 3328  
3224 3329 out:
3225 3330 cfg80211_unlock_rdev(rdev);
... ... @@ -3506,6 +3611,7 @@
3506 3611 struct net_device *dev;
3507 3612 struct cfg80211_ibss_params ibss;
3508 3613 struct wiphy *wiphy;
  3614 + struct cfg80211_cached_keys *connkeys = NULL;
3509 3615 int err;
3510 3616  
3511 3617 memset(&ibss, 0, sizeof(ibss));
3512 3618  
3513 3619  
3514 3620  
... ... @@ -3570,13 +3676,26 @@
3570 3676 }
3571 3677  
3572 3678 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
  3679 + ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
3573 3680  
3574   - err = cfg80211_join_ibss(rdev, dev, &ibss);
  3681 + if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
  3682 + connkeys = nl80211_parse_connkeys(rdev,
  3683 + info->attrs[NL80211_ATTR_KEYS]);
  3684 + if (IS_ERR(connkeys)) {
  3685 + err = PTR_ERR(connkeys);
  3686 + connkeys = NULL;
  3687 + goto out;
  3688 + }
  3689 + }
3575 3690  
  3691 + err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
  3692 +
3576 3693 out:
3577 3694 cfg80211_unlock_rdev(rdev);
3578 3695 dev_put(dev);
3579 3696 unlock_rtnl:
  3697 + if (err)
  3698 + kfree(connkeys);
3580 3699 rtnl_unlock();
3581 3700 return err;
3582 3701 }
... ... @@ -3746,6 +3865,7 @@
3746 3865 struct net_device *dev;
3747 3866 struct cfg80211_connect_params connect;
3748 3867 struct wiphy *wiphy;
  3868 + struct cfg80211_cached_keys *connkeys = NULL;
3749 3869 int err;
3750 3870  
3751 3871 memset(&connect, 0, sizeof(connect));
3752 3872  
3753 3873  
... ... @@ -3810,12 +3930,24 @@
3810 3930 }
3811 3931 }
3812 3932  
3813   - err = cfg80211_connect(rdev, dev, &connect);
  3933 + if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
  3934 + connkeys = nl80211_parse_connkeys(rdev,
  3935 + info->attrs[NL80211_ATTR_KEYS]);
  3936 + if (IS_ERR(connkeys)) {
  3937 + err = PTR_ERR(connkeys);
  3938 + connkeys = NULL;
  3939 + goto out;
  3940 + }
  3941 + }
3814 3942  
  3943 + err = cfg80211_connect(rdev, dev, &connect, connkeys);
  3944 +
3815 3945 out:
3816 3946 cfg80211_unlock_rdev(rdev);
3817 3947 dev_put(dev);
3818 3948 unlock_rtnl:
  3949 + if (err)
  3950 + kfree(connkeys);
3819 3951 rtnl_unlock();
3820 3952 return err;
3821 3953 }
... ... @@ -125,7 +125,9 @@
125 125 params->channel, params->auth_type,
126 126 params->bssid,
127 127 params->ssid, params->ssid_len,
128   - NULL, 0);
  128 + NULL, 0,
  129 + params->key, params->key_len,
  130 + params->key_idx);
129 131 case CFG80211_CONN_ASSOCIATE_NEXT:
130 132 BUG_ON(!rdev->ops->assoc);
131 133 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
... ... @@ -279,8 +281,12 @@
279 281 /* select automatically between only open, shared, leap */
280 282 switch (wdev->conn->params.auth_type) {
281 283 case NL80211_AUTHTYPE_OPEN_SYSTEM:
282   - wdev->conn->params.auth_type =
283   - NL80211_AUTHTYPE_SHARED_KEY;
  284 + if (wdev->connect_keys)
  285 + wdev->conn->params.auth_type =
  286 + NL80211_AUTHTYPE_SHARED_KEY;
  287 + else
  288 + wdev->conn->params.auth_type =
  289 + NL80211_AUTHTYPE_NETWORK_EAP;
284 290 break;
285 291 case NL80211_AUTHTYPE_SHARED_KEY:
286 292 wdev->conn->params.auth_type =
... ... @@ -353,10 +359,8 @@
353 359 #endif
354 360  
355 361 if (status == WLAN_STATUS_SUCCESS &&
356   - wdev->sme_state == CFG80211_SME_IDLE) {
357   - wdev->sme_state = CFG80211_SME_CONNECTED;
358   - return;
359   - }
  362 + wdev->sme_state == CFG80211_SME_IDLE)
  363 + goto success;
360 364  
361 365 if (wdev->sme_state != CFG80211_SME_CONNECTING)
362 366 return;
363 367  
364 368  
... ... @@ -370,24 +374,29 @@
370 374 if (wdev->conn)
371 375 wdev->conn->state = CFG80211_CONN_IDLE;
372 376  
373   - if (status == WLAN_STATUS_SUCCESS) {
374   - bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
375   - wdev->ssid, wdev->ssid_len,
376   - WLAN_CAPABILITY_ESS,
377   - WLAN_CAPABILITY_ESS);
378   -
379   - if (WARN_ON(!bss))
380   - return;
381   -
382   - cfg80211_hold_bss(bss_from_pub(bss));
383   - wdev->current_bss = bss_from_pub(bss);
384   -
385   - wdev->sme_state = CFG80211_SME_CONNECTED;
386   - } else {
  377 + if (status != WLAN_STATUS_SUCCESS) {
387 378 wdev->sme_state = CFG80211_SME_IDLE;
388 379 kfree(wdev->conn);
389 380 wdev->conn = NULL;
  381 + kfree(wdev->connect_keys);
  382 + wdev->connect_keys = NULL;
  383 + return;
390 384 }
  385 +
  386 + bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
  387 + wdev->ssid, wdev->ssid_len,
  388 + WLAN_CAPABILITY_ESS,
  389 + WLAN_CAPABILITY_ESS);
  390 +
  391 + if (WARN_ON(!bss))
  392 + return;
  393 +
  394 + cfg80211_hold_bss(bss_from_pub(bss));
  395 + wdev->current_bss = bss_from_pub(bss);
  396 +
  397 + success:
  398 + wdev->sme_state = CFG80211_SME_CONNECTED;
  399 + cfg80211_upload_connect_keys(wdev);
391 400 }
392 401  
393 402 void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
... ... @@ -516,6 +525,8 @@
516 525 size_t ie_len, u16 reason, bool from_ap)
517 526 {
518 527 struct wireless_dev *wdev = dev->ieee80211_ptr;
  528 + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
  529 + int i;
519 530 #ifdef CONFIG_WIRELESS_EXT
520 531 union iwreq_data wrqu;
521 532 #endif
522 533  
... ... @@ -543,9 +554,16 @@
543 554 wdev->conn = NULL;
544 555 }
545 556  
546   - nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
547   - reason, ie, ie_len, from_ap);
  557 + nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
548 558  
  559 + /*
  560 + * Delete all the keys ... pairwise keys can't really
  561 + * exist any more anyway, but default keys might.
  562 + */
  563 + if (rdev->ops->del_key)
  564 + for (i = 0; i < 6; i++)
  565 + rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
  566 +
549 567 #ifdef CONFIG_WIRELESS_EXT
550 568 memset(&wrqu, 0, sizeof(wrqu));
551 569 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
... ... @@ -580,7 +598,8 @@
580 598  
581 599 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
582 600 struct net_device *dev,
583   - struct cfg80211_connect_params *connect)
  601 + struct cfg80211_connect_params *connect,
  602 + struct cfg80211_cached_keys *connkeys)
584 603 {
585 604 struct wireless_dev *wdev = dev->ieee80211_ptr;
586 605 int err;
... ... @@ -590,6 +609,24 @@
590 609 if (wdev->sme_state != CFG80211_SME_IDLE)
591 610 return -EALREADY;
592 611  
  612 + if (WARN_ON(wdev->connect_keys)) {
  613 + kfree(wdev->connect_keys);
  614 + wdev->connect_keys = NULL;
  615 + }
  616 +
  617 + if (connkeys && connkeys->def >= 0) {
  618 + int idx;
  619 +
  620 + idx = connkeys->def;
  621 + /* If given a WEP key we may need it for shared key auth */
  622 + if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 ||
  623 + connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) {
  624 + connect->key_idx = idx;
  625 + connect->key = connkeys->params[idx].key;
  626 + connect->key_len = connkeys->params[idx].key_len;
  627 + }
  628 + }
  629 +
593 630 if (!rdev->ops->connect) {
594 631 if (!rdev->ops->auth || !rdev->ops->assoc)
595 632 return -EOPNOTSUPP;
... ... @@ -640,6 +677,7 @@
640 677 cfg80211_get_conn_bss(wdev);
641 678  
642 679 wdev->sme_state = CFG80211_SME_CONNECTING;
  680 + wdev->connect_keys = connkeys;
643 681  
644 682 /* we're good if we have both BSSID and channel */
645 683 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
646 684  
647 685  
... ... @@ -662,13 +700,16 @@
662 700 kfree(wdev->conn);
663 701 wdev->conn = NULL;
664 702 wdev->sme_state = CFG80211_SME_IDLE;
  703 + wdev->connect_keys = NULL;
665 704 }
666 705  
667 706 return err;
668 707 } else {
669 708 wdev->sme_state = CFG80211_SME_CONNECTING;
  709 + wdev->connect_keys = connkeys;
670 710 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
671 711 if (err) {
  712 + wdev->connect_keys = NULL;
672 713 wdev->sme_state = CFG80211_SME_IDLE;
673 714 return err;
674 715 }
675 716  
... ... @@ -682,12 +723,13 @@
682 723  
683 724 int cfg80211_connect(struct cfg80211_registered_device *rdev,
684 725 struct net_device *dev,
685   - struct cfg80211_connect_params *connect)
  726 + struct cfg80211_connect_params *connect,
  727 + struct cfg80211_cached_keys *connkeys)
686 728 {
687 729 int err;
688 730  
689 731 wdev_lock(dev->ieee80211_ptr);
690   - err = __cfg80211_connect(rdev, dev, connect);
  732 + err = __cfg80211_connect(rdev, dev, connect, connkeys);
691 733 wdev_unlock(dev->ieee80211_ptr);
692 734  
693 735 return err;
... ... @@ -703,6 +745,9 @@
703 745  
704 746 if (wdev->sme_state == CFG80211_SME_IDLE)
705 747 return -EINVAL;
  748 +
  749 + kfree(wdev->connect_keys);
  750 + wdev->connect_keys = NULL;
706 751  
707 752 if (!rdev->ops->disconnect) {
708 753 if (!rdev->ops->deauth)
... ... @@ -141,9 +141,12 @@
141 141 set_mandatory_flags_band(wiphy->bands[band], band);
142 142 }
143 143  
144   -int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
  144 +int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
  145 + struct key_params *params, int key_idx,
145 146 const u8 *mac_addr)
146 147 {
  148 + int i;
  149 +
147 150 if (key_idx > 5)
148 151 return -EINVAL;
149 152  
... ... @@ -197,6 +200,12 @@
197 200 }
198 201 }
199 202  
  203 + for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
  204 + if (params->cipher == rdev->wiphy.cipher_suites[i])
  205 + break;
  206 + if (i == rdev->wiphy.n_cipher_suites)
  207 + return -EINVAL;
  208 +
200 209 return 0;
201 210 }
202 211  
... ... @@ -523,4 +532,34 @@
523 532 return NULL;
524 533 }
525 534 EXPORT_SYMBOL(ieee80211_bss_get_ie);
  535 +
  536 +void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
  537 +{
  538 + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
  539 + struct net_device *dev = wdev->netdev;
  540 + int i;
  541 +
  542 + if (!wdev->connect_keys)
  543 + return;
  544 +
  545 + for (i = 0; i < 6; i++) {
  546 + if (!wdev->connect_keys->params[i].cipher)
  547 + continue;
  548 + if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL,
  549 + &wdev->connect_keys->params[i]))
  550 + printk(KERN_ERR "%s: failed to set key %d\n",
  551 + dev->name, i);
  552 + if (wdev->connect_keys->def == i)
  553 + if (rdev->ops->set_default_key(wdev->wiphy, dev, i))
  554 + printk(KERN_ERR "%s: failed to set defkey %d\n",
  555 + dev->name, i);
  556 + if (wdev->connect_keys->defmgmt == i)
  557 + if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i))
  558 + printk(KERN_ERR "%s: failed to set mgtdef %d\n",
  559 + dev->name, i);
  560 + }
  561 +
  562 + kfree(wdev->connect_keys);
  563 + wdev->connect_keys = NULL;
  564 +}
net/wireless/wext-compat.c
... ... @@ -453,15 +453,32 @@
453 453 }
454 454 EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
455 455  
456   -static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
457   - struct net_device *dev, const u8 *addr,
458   - bool remove, bool tx_key, int idx,
459   - struct key_params *params)
  456 +static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
  457 + struct net_device *dev, const u8 *addr,
  458 + bool remove, bool tx_key, int idx,
  459 + struct key_params *params)
460 460 {
461 461 struct wireless_dev *wdev = dev->ieee80211_ptr;
462   - int err;
  462 + int err, i;
463 463  
  464 + if (!wdev->wext.keys) {
  465 + wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
  466 + GFP_KERNEL);
  467 + if (!wdev->wext.keys)
  468 + return -ENOMEM;
  469 + for (i = 0; i < 6; i++)
  470 + wdev->wext.keys->params[i].key =
  471 + wdev->wext.keys->data[i];
  472 + }
  473 +
  474 + if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
  475 + wdev->iftype != NL80211_IFTYPE_STATION)
  476 + return -EOPNOTSUPP;
  477 +
464 478 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
  479 + if (!wdev->current_bss)
  480 + return -ENOLINK;
  481 +
465 482 if (!rdev->ops->set_default_mgmt_key)
466 483 return -EOPNOTSUPP;
467 484  
468 485  
... ... @@ -471,8 +488,14 @@
471 488 return -EINVAL;
472 489  
473 490 if (remove) {
474   - err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
  491 + err = 0;
  492 + if (wdev->current_bss)
  493 + err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
475 494 if (!err) {
  495 + if (!addr) {
  496 + wdev->wext.keys->params[idx].key_len = 0;
  497 + wdev->wext.keys->params[idx].cipher = 0;
  498 + }
476 499 if (idx == wdev->wext.default_key)
477 500 wdev->wext.default_key = -1;
478 501 else if (idx == wdev->wext.default_mgmt_key)
479 502  
480 503  
481 504  
482 505  
483 506  
484 507  
485 508  
486 509  
487 510  
... ... @@ -486,38 +509,66 @@
486 509 return 0;
487 510  
488 511 return err;
489   - } else {
490   - if (addr)
491   - tx_key = false;
  512 + }
492 513  
493   - if (cfg80211_validate_key_settings(params, idx, addr))
494   - return -EINVAL;
  514 + if (addr)
  515 + tx_key = false;
495 516  
  517 + if (cfg80211_validate_key_settings(rdev, params, idx, addr))
  518 + return -EINVAL;
  519 +
  520 + err = 0;
  521 + if (wdev->current_bss)
496 522 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
497   - if (err)
498   - return err;
  523 + if (err)
  524 + return err;
499 525  
500   - if (tx_key || (!addr && wdev->wext.default_key == -1)) {
  526 + if (!addr) {
  527 + wdev->wext.keys->params[idx] = *params;
  528 + memcpy(wdev->wext.keys->data[idx],
  529 + params->key, params->key_len);
  530 + wdev->wext.keys->params[idx].key =
  531 + wdev->wext.keys->data[idx];
  532 + }
  533 +
  534 + if (params->cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
  535 + (tx_key || (!addr && wdev->wext.default_key == -1))) {
  536 + if (wdev->current_bss)
501 537 err = rdev->ops->set_default_key(&rdev->wiphy,
502 538 dev, idx);
503   - if (!err)
504   - wdev->wext.default_key = idx;
505   - return err;
506   - }
  539 + if (!err)
  540 + wdev->wext.default_key = idx;
  541 + return err;
  542 + }
507 543  
508   - if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
509   - (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
  544 + if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
  545 + (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
  546 + if (wdev->current_bss)
510 547 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
511 548 dev, idx);
512   - if (!err)
513   - wdev->wext.default_mgmt_key = idx;
514   - return err;
515   - }
516   -
517   - return 0;
  549 + if (!err)
  550 + wdev->wext.default_mgmt_key = idx;
  551 + return err;
518 552 }
  553 +
  554 + return 0;
519 555 }
520 556  
  557 +static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
  558 + struct net_device *dev, const u8 *addr,
  559 + bool remove, bool tx_key, int idx,
  560 + struct key_params *params)
  561 +{
  562 + int err;
  563 +
  564 + wdev_lock(dev->ieee80211_ptr);
  565 + err = __cfg80211_set_encryption(rdev, dev, addr, remove,
  566 + tx_key, idx, params);
  567 + wdev_unlock(dev->ieee80211_ptr);
  568 +
  569 + return err;
  570 +}
  571 +
521 572 int cfg80211_wext_siwencode(struct net_device *dev,
522 573 struct iw_request_info *info,
523 574 struct iw_point *erq, char *keybuf)
... ... @@ -528,6 +579,10 @@
528 579 bool remove = false;
529 580 struct key_params params;
530 581  
  582 + if (wdev->iftype != NL80211_IFTYPE_STATION &&
  583 + wdev->iftype != NL80211_IFTYPE_ADHOC)
  584 + return -EOPNOTSUPP;
  585 +
531 586 /* no use -- only MFP (set_default_mgmt_key) is optional */
532 587 if (!rdev->ops->del_key ||
533 588 !rdev->ops->add_key ||
534 589  
... ... @@ -548,9 +603,14 @@
548 603 remove = true;
549 604 else if (erq->length == 0) {
550 605 /* No key data - just set the default TX key index */
551   - err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx);
  606 + err = 0;
  607 + wdev_lock(wdev);
  608 + if (wdev->current_bss)
  609 + err = rdev->ops->set_default_key(&rdev->wiphy,
  610 + dev, idx);
552 611 if (!err)
553 612 wdev->wext.default_key = idx;
  613 + wdev_unlock(wdev);
554 614 return err;
555 615 }
556 616  
... ... @@ -583,6 +643,10 @@
583 643 struct key_params params;
584 644 u32 cipher;
585 645  
  646 + if (wdev->iftype != NL80211_IFTYPE_STATION &&
  647 + wdev->iftype != NL80211_IFTYPE_ADHOC)
  648 + return -EOPNOTSUPP;
  649 +
586 650 /* no use -- only MFP (set_default_mgmt_key) is optional */
587 651 if (!rdev->ops->del_key ||
588 652 !rdev->ops->add_key ||
589 653  
590 654  
... ... @@ -656,37 +720,15 @@
656 720 }
657 721 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
658 722  
659   -struct giwencode_cookie {
660   - size_t buflen;
661   - char *keybuf;
662   -};
663   -
664   -static void giwencode_get_key_cb(void *cookie, struct key_params *params)
665   -{
666   - struct giwencode_cookie *data = cookie;
667   -
668   - if (!params->key) {
669   - data->buflen = 0;
670   - return;
671   - }
672   -
673   - data->buflen = min_t(size_t, data->buflen, params->key_len);
674   - memcpy(data->keybuf, params->key, data->buflen);
675   -}
676   -
677 723 int cfg80211_wext_giwencode(struct net_device *dev,
678 724 struct iw_request_info *info,
679 725 struct iw_point *erq, char *keybuf)
680 726 {
681 727 struct wireless_dev *wdev = dev->ieee80211_ptr;
682   - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
683   - int idx, err;
684   - struct giwencode_cookie data = {
685   - .keybuf = keybuf,
686   - .buflen = erq->length,
687   - };
  728 + int idx;
688 729  
689   - if (!rdev->ops->get_key)
  730 + if (wdev->iftype != NL80211_IFTYPE_STATION &&
  731 + wdev->iftype != NL80211_IFTYPE_ADHOC)
690 732 return -EOPNOTSUPP;
691 733  
692 734 idx = erq->flags & IW_ENCODE_INDEX;
693 735  
... ... @@ -701,21 +743,18 @@
701 743  
702 744 erq->flags = idx + 1;
703 745  
704   - err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data,
705   - giwencode_get_key_cb);
706   - if (!err) {
707   - erq->length = data.buflen;
708   - erq->flags |= IW_ENCODE_ENABLED;
709   - return 0;
710   - }
711   -
712   - if (err == -ENOENT) {
  746 + if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
713 747 erq->flags |= IW_ENCODE_DISABLED;
714 748 erq->length = 0;
715 749 return 0;
716 750 }
717 751  
718   - return err;
  752 + erq->length = min_t(size_t, erq->length,
  753 + wdev->wext.keys->params[idx].key_len);
  754 + memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
  755 + erq->flags |= IW_ENCODE_ENABLED;
  756 +
  757 + return 0;
719 758 }
720 759 EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
721 760  
net/wireless/wext-sme.c
... ... @@ -10,10 +10,11 @@
10 10 #include <net/cfg80211.h>
11 11 #include "nl80211.h"
12 12  
13   -static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
14   - struct wireless_dev *wdev)
  13 +int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
  14 + struct wireless_dev *wdev)
15 15 {
16   - int err;
  16 + struct cfg80211_cached_keys *ck = NULL;
  17 + int err, i;
17 18  
18 19 ASSERT_RDEV_LOCK(rdev);
19 20 ASSERT_WDEV_LOCK(wdev);
... ... @@ -25,10 +26,25 @@
25 26 wdev->wext.connect.ie_len = wdev->wext.ie_len;
26 27 wdev->wext.connect.privacy = wdev->wext.default_key != -1;
27 28  
28   - err = 0;
29   - if (wdev->wext.connect.ssid_len != 0)
30   - err = __cfg80211_connect(rdev, wdev->netdev,
31   - &wdev->wext.connect);
  29 + if (wdev->wext.keys) {
  30 + wdev->wext.keys->def = wdev->wext.default_key;
  31 + wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
  32 + }
  33 +
  34 + if (!wdev->wext.connect.ssid_len)
  35 + return 0;
  36 +
  37 + if (wdev->wext.keys) {
  38 + ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
  39 + if (!ck)
  40 + return -ENOMEM;
  41 + for (i = 0; i < 6; i++)
  42 + ck->params[i].key = ck->data[i];
  43 + }
  44 + err = __cfg80211_connect(rdev, wdev->netdev,
  45 + &wdev->wext.connect, ck);
  46 + if (err)
  47 + kfree(ck);
32 48  
33 49 return err;
34 50 }