summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-09-23 10:42:28 +0200
committerJohannes Berg <johannes.berg@intel.com>2015-09-29 15:56:50 +0200
commitd0a77c6569abe29d921148c45f598bc796084226 (patch)
tree251445b14277b89990b0b0bb4415ed6f5237c22e /net/mac80211
parent416eb9fc29469f036c85b412edf89774d6b34b0f (diff)
downloadlinux-d0a77c6569abe29d921148c45f598bc796084226.tar.bz2
mac80211: allow writing TX PN in debugfs
For certain tests, for example replay detection, it can be useful to be able to influence/set the PN used in outgoing packets. Make it possible to change the TX PN in debugfs. For now, this doesn't support TKIP since I haven't needed it, but there's no reason it couldn't be added if necessary. Note that this must be used very carefully: it could, for example, be used to make "valid replays" where the PN reuse happens on a different TID. This couldn't be done by an attacker since the TID is protected as part of the AAD. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/debugfs_key.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 702ca122c498..7961e7d0b61e 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -2,6 +2,7 @@
* Copyright 2003-2005 Devicescape Software, Inc.
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (C) 2015 Intel Deutschland GmbH
*
* 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
@@ -34,6 +35,14 @@ static const struct file_operations key_ ##name## _ops = { \
.llseek = generic_file_llseek, \
}
+#define KEY_OPS_W(name) \
+static const struct file_operations key_ ##name## _ops = { \
+ .read = key_##name##_read, \
+ .write = key_##name##_write, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
#define KEY_FILE(name, format) \
KEY_READ_##format(name) \
KEY_OPS(name)
@@ -74,6 +83,41 @@ static ssize_t key_algorithm_read(struct file *file,
}
KEY_OPS(algorithm);
+static ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_key *key = file->private_data;
+ u64 pn;
+ int ret;
+
+ switch (key->conf.cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ return -EINVAL;
+ case WLAN_CIPHER_SUITE_TKIP:
+ /* not supported yet */
+ return -EOPNOTSUPP;
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ ret = kstrtou64_from_user(userbuf, count, 16, &pn);
+ if (ret)
+ return ret;
+ /* PN is a 48-bit counter */
+ if (pn >= (1ULL << 48))
+ return -ERANGE;
+ atomic64_set(&key->conf.tx_pn, pn);
+ return count;
+ default:
+ return 0;
+ }
+}
+
static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -110,7 +154,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
}
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
-KEY_OPS(tx_spec);
+KEY_OPS_W(tx_spec);
static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
@@ -278,6 +322,9 @@ KEY_OPS(key);
#define DEBUGFS_ADD(name) \
debugfs_create_file(#name, 0400, key->debugfs.dir, \
key, &key_##name##_ops);
+#define DEBUGFS_ADD_W(name) \
+ debugfs_create_file(#name, 0600, key->debugfs.dir, \
+ key, &key_##name##_ops);
void ieee80211_debugfs_key_add(struct ieee80211_key *key)
{
@@ -310,7 +357,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
DEBUGFS_ADD(keyidx);
DEBUGFS_ADD(hw_key_idx);
DEBUGFS_ADD(algorithm);
- DEBUGFS_ADD(tx_spec);
+ DEBUGFS_ADD_W(tx_spec);
DEBUGFS_ADD(rx_spec);
DEBUGFS_ADD(replays);
DEBUGFS_ADD(icverrors);