aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c168
1 files changed, 105 insertions, 63 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 1b9d87ed143a..ccd676b2f599 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -49,7 +49,7 @@ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
49 49
50static void assert_key_lock(struct ieee80211_local *local) 50static void assert_key_lock(struct ieee80211_local *local)
51{ 51{
52 WARN_ON(!mutex_is_locked(&local->key_mtx)); 52 lockdep_assert_held(&local->key_mtx);
53} 53}
54 54
55static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) 55static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
@@ -60,7 +60,7 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
60 return NULL; 60 return NULL;
61} 61}
62 62
63static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) 63static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
64{ 64{
65 struct ieee80211_sub_if_data *sdata; 65 struct ieee80211_sub_if_data *sdata;
66 struct ieee80211_sta *sta; 66 struct ieee80211_sta *sta;
@@ -69,12 +69,20 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
69 might_sleep(); 69 might_sleep();
70 70
71 if (!key->local->ops->set_key) 71 if (!key->local->ops->set_key)
72 return; 72 goto out_unsupported;
73 73
74 assert_key_lock(key->local); 74 assert_key_lock(key->local);
75 75
76 sta = get_sta_for_key(key); 76 sta = get_sta_for_key(key);
77 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
78 sdata = key->sdata; 86 sdata = key->sdata;
79 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 87 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
80 sdata = container_of(sdata->bss, 88 sdata = container_of(sdata->bss,
@@ -83,14 +91,28 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
83 91
84 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);
85 93
86 if (!ret) 94 if (!ret) {
87 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 95 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
96 return 0;
97 }
88 98
89 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) 99 if (ret != -ENOSPC && ret != -EOPNOTSUPP)
90 printk(KERN_ERR "mac80211-%s: failed to set key " 100 wiphy_err(key->local->hw.wiphy,
91 "(%d, %pM) to hardware (%d)\n", 101 "failed to set key (%d, %pM) to hardware (%d)\n",
92 wiphy_name(key->local->hw.wiphy), 102 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
93 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); 103
104 out_unsupported:
105 switch (key->conf.cipher) {
106 case WLAN_CIPHER_SUITE_WEP40:
107 case WLAN_CIPHER_SUITE_WEP104:
108 case WLAN_CIPHER_SUITE_TKIP:
109 case WLAN_CIPHER_SUITE_CCMP:
110 case WLAN_CIPHER_SUITE_AES_CMAC:
111 /* all of these we can do in software */
112 return 0;
113 default:
114 return -EINVAL;
115 }
94} 116}
95 117
96static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) 118static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
@@ -121,14 +143,33 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
121 sta, &key->conf); 143 sta, &key->conf);
122 144
123 if (ret) 145 if (ret)
124 printk(KERN_ERR "mac80211-%s: failed to remove key " 146 wiphy_err(key->local->hw.wiphy,
125 "(%d, %pM) from hardware (%d)\n", 147 "failed to remove key (%d, %pM) from hardware (%d)\n",
126 wiphy_name(key->local->hw.wiphy), 148 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
127 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
128 149
129 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 150 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
130} 151}
131 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
132static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 173static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
133 int idx) 174 int idx)
134{ 175{
@@ -184,6 +225,7 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
184 225
185static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, 226static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
186 struct sta_info *sta, 227 struct sta_info *sta,
228 bool pairwise,
187 struct ieee80211_key *old, 229 struct ieee80211_key *old,
188 struct ieee80211_key *new) 230 struct ieee80211_key *new)
189{ 231{
@@ -192,8 +234,14 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
192 if (new) 234 if (new)
193 list_add(&new->list, &sdata->key_list); 235 list_add(&new->list, &sdata->key_list);
194 236
195 if (sta) { 237 if (sta && pairwise) {
196 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);
197 } else { 245 } else {
198 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); 246 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
199 247
@@ -227,20 +275,18 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
227 } 275 }
228} 276}
229 277
230struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, 278struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
231 int idx,
232 size_t key_len,
233 const u8 *key_data, 279 const u8 *key_data,
234 size_t seq_len, const u8 *seq) 280 size_t seq_len, const u8 *seq)
235{ 281{
236 struct ieee80211_key *key; 282 struct ieee80211_key *key;
237 int i, j; 283 int i, j, err;
238 284
239 BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); 285 BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
240 286
241 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); 287 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
242 if (!key) 288 if (!key)
243 return NULL; 289 return ERR_PTR(-ENOMEM);
244 290
245 /* 291 /*
246 * Default to software encryption; we'll later upload the 292 * Default to software encryption; we'll later upload the
@@ -249,15 +295,16 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
249 key->conf.flags = 0; 295 key->conf.flags = 0;
250 key->flags = 0; 296 key->flags = 0;
251 297
252 key->conf.alg = alg; 298 key->conf.cipher = cipher;
253 key->conf.keyidx = idx; 299 key->conf.keyidx = idx;
254 key->conf.keylen = key_len; 300 key->conf.keylen = key_len;
255 switch (alg) { 301 switch (cipher) {
256 case ALG_WEP: 302 case WLAN_CIPHER_SUITE_WEP40:
303 case WLAN_CIPHER_SUITE_WEP104:
257 key->conf.iv_len = WEP_IV_LEN; 304 key->conf.iv_len = WEP_IV_LEN;
258 key->conf.icv_len = WEP_ICV_LEN; 305 key->conf.icv_len = WEP_ICV_LEN;
259 break; 306 break;
260 case ALG_TKIP: 307 case WLAN_CIPHER_SUITE_TKIP:
261 key->conf.iv_len = TKIP_IV_LEN; 308 key->conf.iv_len = TKIP_IV_LEN;
262 key->conf.icv_len = TKIP_ICV_LEN; 309 key->conf.icv_len = TKIP_ICV_LEN;
263 if (seq) { 310 if (seq) {
@@ -269,7 +316,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
269 } 316 }
270 } 317 }
271 break; 318 break;
272 case ALG_CCMP: 319 case WLAN_CIPHER_SUITE_CCMP:
273 key->conf.iv_len = CCMP_HDR_LEN; 320 key->conf.iv_len = CCMP_HDR_LEN;
274 key->conf.icv_len = CCMP_MIC_LEN; 321 key->conf.icv_len = CCMP_MIC_LEN;
275 if (seq) { 322 if (seq) {
@@ -278,42 +325,38 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
278 key->u.ccmp.rx_pn[i][j] = 325 key->u.ccmp.rx_pn[i][j] =
279 seq[CCMP_PN_LEN - j - 1]; 326 seq[CCMP_PN_LEN - j - 1];
280 } 327 }
281 break;
282 case ALG_AES_CMAC:
283 key->conf.iv_len = 0;
284 key->conf.icv_len = sizeof(struct ieee80211_mmie);
285 if (seq)
286 for (j = 0; j < 6; j++)
287 key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
288 break;
289 }
290 memcpy(key->conf.key, key_data, key_len);
291 INIT_LIST_HEAD(&key->list);
292
293 if (alg == ALG_CCMP) {
294 /* 328 /*
295 * Initialize AES key state here as an optimization so that 329 * Initialize AES key state here as an optimization so that
296 * it does not need to be initialized for every packet. 330 * it does not need to be initialized for every packet.
297 */ 331 */
298 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); 332 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
299 if (!key->u.ccmp.tfm) { 333 if (IS_ERR(key->u.ccmp.tfm)) {
334 err = PTR_ERR(key->u.ccmp.tfm);
300 kfree(key); 335 kfree(key);
301 return NULL; 336 key = ERR_PTR(err);
302 } 337 }
303 } 338 break;
304 339 case WLAN_CIPHER_SUITE_AES_CMAC:
305 if (alg == ALG_AES_CMAC) { 340 key->conf.iv_len = 0;
341 key->conf.icv_len = sizeof(struct ieee80211_mmie);
342 if (seq)
343 for (j = 0; j < 6; j++)
344 key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
306 /* 345 /*
307 * Initialize AES key state here as an optimization so that 346 * Initialize AES key state here as an optimization so that
308 * it does not need to be initialized for every packet. 347 * it does not need to be initialized for every packet.
309 */ 348 */
310 key->u.aes_cmac.tfm = 349 key->u.aes_cmac.tfm =
311 ieee80211_aes_cmac_key_setup(key_data); 350 ieee80211_aes_cmac_key_setup(key_data);
312 if (!key->u.aes_cmac.tfm) { 351 if (IS_ERR(key->u.aes_cmac.tfm)) {
352 err = PTR_ERR(key->u.aes_cmac.tfm);
313 kfree(key); 353 kfree(key);
314 return NULL; 354 key = ERR_PTR(err);
315 } 355 }
356 break;
316 } 357 }
358 memcpy(key->conf.key, key_data, key_len);
359 INIT_LIST_HEAD(&key->list);
317 360
318 return key; 361 return key;
319} 362}
@@ -326,9 +369,9 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
326 if (key->local) 369 if (key->local)
327 ieee80211_key_disable_hw_accel(key); 370 ieee80211_key_disable_hw_accel(key);
328 371
329 if (key->conf.alg == ALG_CCMP) 372 if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
330 ieee80211_aes_key_free(key->u.ccmp.tfm); 373 ieee80211_aes_key_free(key->u.ccmp.tfm);
331 if (key->conf.alg == ALG_AES_CMAC) 374 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
332 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 375 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
333 if (key->local) 376 if (key->local)
334 ieee80211_debugfs_key_remove(key); 377 ieee80211_debugfs_key_remove(key);
@@ -336,12 +379,13 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
336 kfree(key); 379 kfree(key);
337} 380}
338 381
339void ieee80211_key_link(struct ieee80211_key *key, 382int ieee80211_key_link(struct ieee80211_key *key,
340 struct ieee80211_sub_if_data *sdata, 383 struct ieee80211_sub_if_data *sdata,
341 struct sta_info *sta) 384 struct sta_info *sta)
342{ 385{
343 struct ieee80211_key *old_key; 386 struct ieee80211_key *old_key;
344 int idx; 387 int idx, ret;
388 bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
345 389
346 BUG_ON(!sdata); 390 BUG_ON(!sdata);
347 BUG_ON(!key); 391 BUG_ON(!key);
@@ -358,13 +402,6 @@ void ieee80211_key_link(struct ieee80211_key *key,
358 */ 402 */
359 if (test_sta_flags(sta, WLAN_STA_WME)) 403 if (test_sta_flags(sta, WLAN_STA_WME))
360 key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; 404 key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
361
362 /*
363 * This key is for a specific sta interface,
364 * inform the driver that it should try to store
365 * this key as pairwise key.
366 */
367 key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
368 } else { 405 } else {
369 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 406 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
370 struct sta_info *ap; 407 struct sta_info *ap;
@@ -386,19 +423,23 @@ void ieee80211_key_link(struct ieee80211_key *key,
386 423
387 mutex_lock(&sdata->local->key_mtx); 424 mutex_lock(&sdata->local->key_mtx);
388 425
389 if (sta) 426 if (sta && pairwise)
390 old_key = sta->key; 427 old_key = sta->ptk;
428 else if (sta)
429 old_key = sta->gtk[idx];
391 else 430 else
392 old_key = sdata->keys[idx]; 431 old_key = sdata->keys[idx];
393 432
394 __ieee80211_key_replace(sdata, sta, old_key, key); 433 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
395 __ieee80211_key_destroy(old_key); 434 __ieee80211_key_destroy(old_key);
396 435
397 ieee80211_debugfs_key_add(key); 436 ieee80211_debugfs_key_add(key);
398 437
399 ieee80211_key_enable_hw_accel(key); 438 ret = ieee80211_key_enable_hw_accel(key);
400 439
401 mutex_unlock(&sdata->local->key_mtx); 440 mutex_unlock(&sdata->local->key_mtx);
441
442 return ret;
402} 443}
403 444
404static void __ieee80211_key_free(struct ieee80211_key *key) 445static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -408,7 +449,8 @@ static void __ieee80211_key_free(struct ieee80211_key *key)
408 */ 449 */
409 if (key->sdata) 450 if (key->sdata)
410 __ieee80211_key_replace(key->sdata, key->sta, 451 __ieee80211_key_replace(key->sdata, key->sta,
411 key, NULL); 452 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
453 key, NULL);
412 __ieee80211_key_destroy(key); 454 __ieee80211_key_destroy(key);
413} 455}
414 456