[MAC80211]: rework key handling
This moves all the key handling code out from ieee80211_ioctl.c
into key.c and also does the following changes including documentation
updates in mac80211.h:
1) Turn off hardware acceleration for keys when the interface
is down. This is necessary because otherwise monitor
interfaces could be decrypting frames for other interfaces
that are down at the moment. Also, it should go some way
towards better suspend/resume support, in any case the
routines used here could be used for that as well.
Additionally, this makes the driver interface nicer, keys
for a specific local MAC address are only ever present
while an interface with that MAC address is enabled.
2) Change driver set_key() callback interface to allow only
return values of -ENOSPC, -EOPNOTSUPP and 0, warn on all
other return values. This allows debugging the stack when
a driver notices it's handed a key while it is down.
3) Invert the flag meaning to KEY_FLAG_UPLOADED_TO_HARDWARE.
4) Remove REMOVE_ALL_KEYS command as it isn't used nor do we
want to use it, we'll use DISABLE_KEY for each key. It is
hard to use REMOVE_ALL_KEYS because we can handle multiple
virtual interfaces with different key configuration, so we'd
have to keep track of a lot of state for this and that isn't
worth it.
5) Warn when disabling a key fails, it musn't.
6) Remove IEEE80211_HW_NO_TKIP_WMM_HWACCEL in favour of per-key
IEEE80211_KEY_FLAG_WMM_STA to let driver sort it out itself.
7) Tell driver that a (non-WEP) key is used only for transmission
by using an all-zeroes station MAC address when configuring.
8) Change the set_key() callback to have access to the local MAC
address the key is being added for.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 3437fa1..ec8c739 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -399,19 +399,34 @@
ALG_CCMP,
} ieee80211_key_alg;
+/*
+ * This flag indiciates that the station this key is being
+ * configured for may use QoS. If your hardware cannot handle
+ * that situation it should reject that key.
+ */
+#define IEEE80211_KEY_FLAG_WMM_STA (1<<0)
+
struct ieee80211_key_conf {
- /* shall be changed by the driver to anything but HW_KEY_IDX_INVALID */
+ /*
+ * To be set by the driver to the key index it would like to
+ * get in the ieee80211_tx_control.key_idx which defaults
+ * to HW_KEY_IDX_INVALID so that shouldn't be used.
+ */
int hw_key_idx;
+ /* key algorithm, ALG_NONE should never be seen by the driver */
ieee80211_key_alg alg;
- int keylen;
+ /* key flags, see above */
+ u8 flags;
-#define IEEE80211_KEY_FORCE_SW_ENCRYPT (1<<0) /* to be cleared by low-level
- driver */
- u32 flags; /* key configuration flags defined above */
+ /* key index: 0-3 */
+ s8 keyidx;
- s8 keyidx; /* WEP key index */
+ /* length of key material */
+ u8 keylen;
+
+ /* the key material */
u8 key[0];
};
@@ -419,7 +434,7 @@
#define IEEE80211_SEQ_COUNTER_TX 1
typedef enum {
- SET_KEY, DISABLE_KEY, REMOVE_ALL_KEYS,
+ SET_KEY, DISABLE_KEY,
} set_key_cmd;
/* This is driver-visible part of the per-hw state the stack keeps. */
@@ -492,8 +507,7 @@
/* hole at 6 */
- /* Force software encryption for TKIP packets if WMM is enabled. */
-#define IEEE80211_HW_NO_TKIP_WMM_HWACCEL (1<<7)
+/* hole at 7 */
/*
* Some devices handle Michael MIC internally and do not include MIC in
@@ -627,12 +641,31 @@
*
* This is called to enable hardware acceleration of encryption and
* decryption. The address will be the broadcast address for default
- * keys and the other station's hardware address for individual keys.
+ * keys, the other station's hardware address for individual keys or
+ * the zero address for keys that will be used only for transmission.
+ *
+ * The local_address parameter will always be set to our own address,
+ * this is only relevant if you support multiple local addresses.
+ *
* When transmitting, the TX control data will use the hw_key_idx
* selected by the low-level driver.
+ *
+ * Return 0 if the key is now in use, -EOPNOTSUPP or -ENOSPC if it
+ * couldn't be added; if you return 0 then hw_key_idx must be
+ * assigned to something other than HW_KEY_IDX_INVALID. When the cmd
+ * is DISABLE_KEY then it must succeed.
+ *
+ * This callback can sleep, and is only called between add_interface
+ * and remove_interface calls, i.e. while the interface with the
+ * given local_address is enabled.
+ *
+ * The ieee80211_key_conf structure pointed to by the key parameter
+ * is guaranteed to be valid until another call to set_key removes
+ * it, but it can only be used as a cookie to differentiate keys.
*/
int (*set_key)(struct ieee80211_hw *hw, set_key_cmd cmd,
- u8 *address, struct ieee80211_key_conf *key);
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key);
/*
* Set TX key index for default/broadcast keys. This is needed in cases
@@ -640,6 +673,10 @@
* is not set), in other cases, this function pointer can be set to
* NULL since the IEEE 802.11 module takes care of selecting the key
* index for each TX frame.
+ *
+ * TODO: If you use this callback in your driver tell us if you need
+ * any other information from it to make it easier, like the
+ * key_conf instead.
*/
int (*set_key_idx)(struct ieee80211_hw *hw, int idx);