aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-01-08 06:32:02 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:03 -0500
commit3cfcf6ac6d69dc290e96416731eea5c88ac7d426 (patch)
tree35bc626e2e3f7c37a7eb50c1f057adb4830eccc6 /net/mac80211/key.c
parent765cb46a3fc856245ea68a7c961ac87c77e4ae2d (diff)
mac80211: 802.11w - Use BIP (AES-128-CMAC)
Add mechanism for managing BIP keys (IGTK) and integrate BIP into the TX/RX paths. Signed-off-by: Jouni Malinen <j@w1.fi> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index b0a025c9b615..19b480de4bbc 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -18,6 +18,7 @@
18#include "ieee80211_i.h" 18#include "ieee80211_i.h"
19#include "debugfs_key.h" 19#include "debugfs_key.h"
20#include "aes_ccm.h" 20#include "aes_ccm.h"
21#include "aes_cmac.h"
21 22
22 23
23/** 24/**
@@ -215,13 +216,38 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
215 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 216 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
216} 217}
217 218
219static void
220__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
221{
222 struct ieee80211_key *key = NULL;
223
224 if (idx >= NUM_DEFAULT_KEYS &&
225 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
226 key = sdata->keys[idx];
227
228 rcu_assign_pointer(sdata->default_mgmt_key, key);
229
230 if (key)
231 add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY);
232}
233
234void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
235 int idx)
236{
237 unsigned long flags;
238
239 spin_lock_irqsave(&sdata->local->key_lock, flags);
240 __ieee80211_set_default_mgmt_key(sdata, idx);
241 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
242}
243
218 244
219static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, 245static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
220 struct sta_info *sta, 246 struct sta_info *sta,
221 struct ieee80211_key *old, 247 struct ieee80211_key *old,
222 struct ieee80211_key *new) 248 struct ieee80211_key *new)
223{ 249{
224 int idx, defkey; 250 int idx, defkey, defmgmtkey;
225 251
226 if (new) 252 if (new)
227 list_add(&new->list, &sdata->key_list); 253 list_add(&new->list, &sdata->key_list);
@@ -237,13 +263,19 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
237 idx = new->conf.keyidx; 263 idx = new->conf.keyidx;
238 264
239 defkey = old && sdata->default_key == old; 265 defkey = old && sdata->default_key == old;
266 defmgmtkey = old && sdata->default_mgmt_key == old;
240 267
241 if (defkey && !new) 268 if (defkey && !new)
242 __ieee80211_set_default_key(sdata, -1); 269 __ieee80211_set_default_key(sdata, -1);
270 if (defmgmtkey && !new)
271 __ieee80211_set_default_mgmt_key(sdata, -1);
243 272
244 rcu_assign_pointer(sdata->keys[idx], new); 273 rcu_assign_pointer(sdata->keys[idx], new);
245 if (defkey && new) 274 if (defkey && new)
246 __ieee80211_set_default_key(sdata, new->conf.keyidx); 275 __ieee80211_set_default_key(sdata, new->conf.keyidx);
276 if (defmgmtkey && new)
277 __ieee80211_set_default_mgmt_key(sdata,
278 new->conf.keyidx);
247 } 279 }
248 280
249 if (old) { 281 if (old) {
@@ -262,7 +294,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
262{ 294{
263 struct ieee80211_key *key; 295 struct ieee80211_key *key;
264 296
265 BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS); 297 BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
266 298
267 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); 299 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
268 if (!key) 300 if (!key)
@@ -291,6 +323,10 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
291 key->conf.iv_len = CCMP_HDR_LEN; 323 key->conf.iv_len = CCMP_HDR_LEN;
292 key->conf.icv_len = CCMP_MIC_LEN; 324 key->conf.icv_len = CCMP_MIC_LEN;
293 break; 325 break;
326 case ALG_AES_CMAC:
327 key->conf.iv_len = 0;
328 key->conf.icv_len = sizeof(struct ieee80211_mmie);
329 break;
294 } 330 }
295 memcpy(key->conf.key, key_data, key_len); 331 memcpy(key->conf.key, key_data, key_len);
296 INIT_LIST_HEAD(&key->list); 332 INIT_LIST_HEAD(&key->list);
@@ -308,6 +344,19 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
308 } 344 }
309 } 345 }
310 346
347 if (alg == ALG_AES_CMAC) {
348 /*
349 * Initialize AES key state here as an optimization so that
350 * it does not need to be initialized for every packet.
351 */
352 key->u.aes_cmac.tfm =
353 ieee80211_aes_cmac_key_setup(key_data);
354 if (!key->u.aes_cmac.tfm) {
355 kfree(key);
356 return NULL;
357 }
358 }
359
311 return key; 360 return key;
312} 361}
313 362
@@ -461,6 +510,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
461 510
462 if (key->conf.alg == ALG_CCMP) 511 if (key->conf.alg == ALG_CCMP)
463 ieee80211_aes_key_free(key->u.ccmp.tfm); 512 ieee80211_aes_key_free(key->u.ccmp.tfm);
513 if (key->conf.alg == ALG_AES_CMAC)
514 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
464 ieee80211_debugfs_key_remove(key); 515 ieee80211_debugfs_key_remove(key);
465 516
466 kfree(key); 517 kfree(key);
@@ -483,6 +534,7 @@ static void __ieee80211_key_todo(void)
483 list_del_init(&key->todo); 534 list_del_init(&key->todo);
484 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | 535 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
485 KEY_FLAG_TODO_DEFKEY | 536 KEY_FLAG_TODO_DEFKEY |
537 KEY_FLAG_TODO_DEFMGMTKEY |
486 KEY_FLAG_TODO_HWACCEL_ADD | 538 KEY_FLAG_TODO_HWACCEL_ADD |
487 KEY_FLAG_TODO_HWACCEL_REMOVE | 539 KEY_FLAG_TODO_HWACCEL_REMOVE |
488 KEY_FLAG_TODO_DELETE); 540 KEY_FLAG_TODO_DELETE);
@@ -500,6 +552,11 @@ static void __ieee80211_key_todo(void)
500 ieee80211_debugfs_key_add_default(key->sdata); 552 ieee80211_debugfs_key_add_default(key->sdata);
501 work_done = true; 553 work_done = true;
502 } 554 }
555 if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) {
556 ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
557 ieee80211_debugfs_key_add_mgmt_default(key->sdata);
558 work_done = true;
559 }
503 if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { 560 if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
504 ieee80211_key_enable_hw_accel(key); 561 ieee80211_key_enable_hw_accel(key);
505 work_done = true; 562 work_done = true;
@@ -535,6 +592,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
535 ieee80211_key_lock(); 592 ieee80211_key_lock();
536 593
537 ieee80211_debugfs_key_remove_default(sdata); 594 ieee80211_debugfs_key_remove_default(sdata);
595 ieee80211_debugfs_key_remove_mgmt_default(sdata);
538 596
539 spin_lock_irqsave(&sdata->local->key_lock, flags); 597 spin_lock_irqsave(&sdata->local->key_lock, flags);
540 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 598 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)