From 2c8dccc77420fb7433da5674818959d3499d35be Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Apr 2008 15:14:40 -0400 Subject: mac80211: rename files This patch renames all mac80211 files (except ieee80211_i.h) to get rid of the useless ieee80211_ prefix. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/key.h | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 net/mac80211/key.h (limited to 'net/mac80211/key.h') diff --git a/net/mac80211/key.h b/net/mac80211/key.h new file mode 100644 index 000000000000..467890c6fe81 --- /dev/null +++ b/net/mac80211/key.h @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2004, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef IEEE80211_KEY_H +#define IEEE80211_KEY_H + +#include +#include +#include +#include +#include + +/* ALG_TKIP + * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block: + * Temporal Encryption Key (128 bits) + * Temporal Authenticator Tx MIC Key (64 bits) + * Temporal Authenticator Rx MIC Key (64 bits) + */ + +#define WEP_IV_LEN 4 +#define WEP_ICV_LEN 4 + +#define ALG_TKIP_KEY_LEN 32 +/* Starting offsets for each key */ +#define ALG_TKIP_TEMP_ENCR_KEY 0 +#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16 +#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24 +#define TKIP_IV_LEN 8 +#define TKIP_ICV_LEN 4 + +#define ALG_CCMP_KEY_LEN 16 +#define CCMP_HDR_LEN 8 +#define CCMP_MIC_LEN 8 +#define CCMP_TK_LEN 16 +#define CCMP_PN_LEN 6 + +#define NUM_RX_DATA_QUEUES 17 + +struct ieee80211_local; +struct ieee80211_sub_if_data; +struct sta_info; + +/** + * enum ieee80211_internal_key_flags - internal key flags + * + * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present + * in the hardware for TX crypto hardware acceleration. + * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an + * RCU grace period, no longer be reachable other than from the + * todo list. + * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration. + * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. + * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. + */ +enum ieee80211_internal_key_flags { + KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), + KEY_FLAG_TODO_DELETE = BIT(1), + KEY_FLAG_TODO_HWACCEL = BIT(2), + KEY_FLAG_TODO_DEFKEY = BIT(3), + KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4), +}; + +struct ieee80211_key { + struct ieee80211_local *local; + struct ieee80211_sub_if_data *sdata; + struct sta_info *sta; + + /* for sdata list */ + struct list_head list; + /* for todo list */ + struct list_head todo; + + /* protected by todo lock! */ + unsigned int flags; + + union { + struct { + /* last used TSC */ + u32 iv32; + u16 iv16; + u16 p1k[5]; + int tx_initialized; + + /* last received RSC */ + u32 iv32_rx[NUM_RX_DATA_QUEUES]; + u16 iv16_rx[NUM_RX_DATA_QUEUES]; + u16 p1k_rx[NUM_RX_DATA_QUEUES][5]; + int rx_initialized[NUM_RX_DATA_QUEUES]; + } tkip; + struct { + u8 tx_pn[6]; + u8 rx_pn[NUM_RX_DATA_QUEUES][6]; + struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCCMPReplays */ + /* scratch buffers for virt_to_page() (crypto API) */ +#ifndef AES_BLOCK_LEN +#define AES_BLOCK_LEN 16 +#endif + u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; + u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; + } ccmp; + } u; + + /* number of times this key has been used */ + int tx_rx_count; + +#ifdef CONFIG_MAC80211_DEBUGFS + struct { + struct dentry *stalink; + struct dentry *dir; + struct dentry *keylen; + struct dentry *flags; + struct dentry *keyidx; + struct dentry *hw_key_idx; + struct dentry *tx_rx_count; + struct dentry *algorithm; + struct dentry *tx_spec; + struct dentry *rx_spec; + struct dentry *replays; + struct dentry *key; + struct dentry *ifindex; + } debugfs; +#endif + + /* + * key config, must be last because it contains key + * material as variable length member + */ + struct ieee80211_key_conf conf; +}; + +struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, + int idx, + size_t key_len, + const u8 *key_data); +/* + * Insert a key into data structures (sdata, sta if necessary) + * to make it used, free old key. + */ +void ieee80211_key_link(struct ieee80211_key *key, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta); +void ieee80211_key_free(struct ieee80211_key *key); +void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); +void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); +void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); +void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); + +void ieee80211_key_todo(void); + +#endif /* IEEE80211_KEY_H */ -- cgit v1.2.3 From d9c58f30b08bfe1e689537af5bc855a76d0fae25 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Apr 2008 16:46:36 -0400 Subject: mac80211: fix key debugfs default_key link The default_key symlink points to the key index rather than they key counter, fix it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_key.c | 3 ++- net/mac80211/key.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'net/mac80211/key.h') diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index bf7027e9ce9f..879e7210458a 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -195,6 +195,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) return; sprintf(buf, "%d", keycount); + key->debugfs.cnt = keycount; keycount++; key->debugfs.dir = debugfs_create_dir(buf, key->local->debugfs.keys); @@ -258,7 +259,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) if (!sdata->debugfsdir) return; - sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx); + sprintf(buf, "../keys/%d", sdata->default_key->debugfs.cnt); sdata->debugfs.default_key = debugfs_create_symlink("default_key", sdata->debugfsdir, buf); } diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 467890c6fe81..5d48518985b3 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -125,6 +125,7 @@ struct ieee80211_key { struct dentry *replays; struct dentry *key; struct dentry *ifindex; + int cnt; } debugfs; #endif -- cgit v1.2.3 From 3a245766901a9dfdc3f53457a7954b369b50f281 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Apr 2008 16:45:37 +0200 Subject: mac80211: fix key hwaccel race The previous key locking patch left a small race: it would be possible to add a key and take the interface down before the key todo is run so that hwaccel for that key is enabled on an interface that is down. Avoid this by running the todo list when an interface is brought up or down. This patch also fixes a small bug: before this change, a few functions used the key list without the lock that protects it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/key.c | 84 +++++++++++++++++++++++++++++++++--------------------- net/mac80211/key.h | 11 ++++--- 2 files changed, 59 insertions(+), 36 deletions(-) (limited to 'net/mac80211/key.h') diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 711e36e54ff8..acf8d0370a37 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -355,61 +355,74 @@ void ieee80211_key_link(struct ieee80211_key *key, add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); if (netif_running(sdata->dev)) - add_todo(key, KEY_FLAG_TODO_HWACCEL); + add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); } -void ieee80211_key_free(struct ieee80211_key *key) +static void __ieee80211_key_free(struct ieee80211_key *key) { - unsigned long flags; - - if (!key) - return; - /* * Replace key with nothingness if it was ever used. */ - if (key->sdata) { - spin_lock_irqsave(&key->sdata->local->sta_lock, flags); + if (key->sdata) __ieee80211_key_replace(key->sdata, key->sta, key, NULL); - spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags); - } add_todo(key, KEY_FLAG_TODO_DELETE); } -void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) +void ieee80211_key_free(struct ieee80211_key *key) { - struct ieee80211_key *key; - - might_sleep(); + unsigned long flags; - if (WARN_ON(!netif_running(sdata->dev))) + if (!key) return; - ieee80211_key_lock(); + spin_lock_irqsave(&key->sdata->local->sta_lock, flags); + __ieee80211_key_free(key); + spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags); +} + +/* + * To be safe against concurrent manipulations of the list (which shouldn't + * actually happen) we need to hold the spinlock. But under the spinlock we + * can't actually do much, so we defer processing to the todo list. Then run + * the todo list to be sure the operation and possibly previously pending + * operations are completed. + */ +static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata, + u32 todo_flags) +{ + struct ieee80211_key *key; + unsigned long flags; + might_sleep(); + + spin_lock_irqsave(&sdata->local->sta_lock, flags); list_for_each_entry(key, &sdata->key_list, list) - ieee80211_key_enable_hw_accel(key); + add_todo(key, todo_flags); + spin_unlock_irqrestore(&sdata->local->sta_lock, flags); - ieee80211_key_unlock(); + ieee80211_key_todo(); } -void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) +void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_key *key; + ASSERT_RTNL(); - might_sleep(); + if (WARN_ON(!netif_running(sdata->dev))) + return; - ieee80211_key_lock(); + ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); +} - list_for_each_entry(key, &sdata->key_list, list) - ieee80211_key_disable_hw_accel(key); +void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) +{ + ASSERT_RTNL(); - ieee80211_key_unlock(); + ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE); } -static void __ieee80211_key_free(struct ieee80211_key *key) +static void __ieee80211_key_destroy(struct ieee80211_key *key) { if (!key) return; @@ -440,7 +453,8 @@ static void __ieee80211_key_todo(void) list_del_init(&key->todo); todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | KEY_FLAG_TODO_DEFKEY | - KEY_FLAG_TODO_HWACCEL | + KEY_FLAG_TODO_HWACCEL_ADD | + KEY_FLAG_TODO_HWACCEL_REMOVE | KEY_FLAG_TODO_DELETE); key->flags &= ~todoflags; spin_unlock(&todo_lock); @@ -456,12 +470,16 @@ static void __ieee80211_key_todo(void) ieee80211_debugfs_key_add_default(key->sdata); work_done = true; } - if (todoflags & KEY_FLAG_TODO_HWACCEL) { + if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { ieee80211_key_enable_hw_accel(key); work_done = true; } + if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) { + ieee80211_key_disable_hw_accel(key); + work_done = true; + } if (todoflags & KEY_FLAG_TODO_DELETE) { - __ieee80211_key_free(key); + __ieee80211_key_destroy(key); work_done = true; } @@ -482,14 +500,16 @@ void ieee80211_key_todo(void) void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) { struct ieee80211_key *key, *tmp; - LIST_HEAD(tmp_list); + unsigned long flags; ieee80211_key_lock(); ieee80211_debugfs_key_remove_default(sdata); + spin_lock_irqsave(&sdata->local->sta_lock, flags); list_for_each_entry_safe(key, tmp, &sdata->key_list, list) - ieee80211_key_free(key); + __ieee80211_key_free(key); + spin_unlock_irqrestore(&sdata->local->sta_lock, flags); __ieee80211_key_todo(); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 5d48518985b3..f52c3df1fe9a 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -54,16 +54,19 @@ struct sta_info; * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an * RCU grace period, no longer be reachable other than from the * todo list. - * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration. + * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration. + * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware + * acceleration. * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. */ enum ieee80211_internal_key_flags { KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), KEY_FLAG_TODO_DELETE = BIT(1), - KEY_FLAG_TODO_HWACCEL = BIT(2), - KEY_FLAG_TODO_DEFKEY = BIT(3), - KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4), + KEY_FLAG_TODO_HWACCEL_ADD = BIT(2), + KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), + KEY_FLAG_TODO_DEFKEY = BIT(4), + KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), }; struct ieee80211_key { -- cgit v1.2.3