Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f20fc24 authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller
Browse files

[MAC80211]: embed key conf in key, fix driver interface



This patch embeds the struct ieee80211_key_conf into struct ieee80211_key
and thus avoids allocations and having data present twice.

This required some more changes:
 1) The removal of the IEEE80211_KEY_DEFAULT_TX_KEY key flag.
    This flag isn't used by drivers nor should it be since
    we have a set_key_idx() callback. Maybe that callback needs
    to be extended to include the key conf, but only a driver that
    requires it will tell.
 2) The removal of the IEEE80211_KEY_DEFAULT_WEP_ONLY key flag.
    This flag is global, so it shouldn't be passed in the key
    conf structure. Pass it to the function instead.

Also, this patch removes the AID parameter to the set_key() callback
because it is currently unused and the hardware currently cannot know
about the AID anyway. I suspect this was used with some hardware that
actually selected the AID itself, but that functionality was removed.

Additionally, I've removed the ALG_NULL key algorithm since we have
ALG_NONE.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Acked-by: default avatarMichael Wu <flamingice@sourmilk.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 13262ffd
Loading
Loading
Loading
Loading
+27 −24
Original line number Diff line number Diff line
@@ -205,8 +205,8 @@ struct ieee80211_tx_control {
				 * is not implemented by the driver */
	u8 power_level;		/* per-packet transmit power level, in dBm */
	u8 antenna_sel_tx; 	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
	s8 key_idx;		/* -1 = do not encrypt, >= 0 keyidx from
				 * hw->set_key() */
	s8 key_idx;		/* HW_KEY_IDX_INVALID = do not encrypt,
				 * other values: keyidx from hw->set_key() */
	u8 icv_len;		/* length of the ICV/MIC field in octets */
	u8 iv_len;		/* length of the IV field in octets */
	u8 tkip_key[16];	/* generated phase2/phase1 key for hw TKIP */
@@ -392,26 +392,23 @@ struct ieee80211_if_conf {
	struct ieee80211_tx_control *beacon_control;
};

typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
ieee80211_key_alg;

typedef enum {
	ALG_NONE,
	ALG_WEP,
	ALG_TKIP,
	ALG_CCMP,
} ieee80211_key_alg;

struct ieee80211_key_conf {
	/* shall be changed by the driver to anything but HW_KEY_IDX_INVALID */
	int hw_key_idx;

	int hw_key_idx;			/* filled + used by low-level driver */
	ieee80211_key_alg alg;

	int keylen;

#define IEEE80211_KEY_FORCE_SW_ENCRYPT (1<<0) /* to be cleared by low-level
						 driver */
#define IEEE80211_KEY_DEFAULT_TX_KEY   (1<<1) /* This key is the new default TX
						 key (used only for broadcast
						 keys). */
#define IEEE80211_KEY_DEFAULT_WEP_ONLY (1<<2) /* static WEP is the only
						 configured security policy;
						 this allows some low-level
						 drivers to determine when
						 hwaccel can be used */
	u32 flags; /* key configuration flags defined above */

	s8 keyidx;			/* WEP key index */
@@ -625,20 +622,26 @@ struct ieee80211_ops {
	 * Must be atomic. */
	int (*set_tim)(struct ieee80211_hw *hw, int aid, int set);

	/* Set encryption key. IEEE 802.11 module calls this function to set
	 * encryption keys. addr is ff:ff:ff:ff:ff:ff for default keys and
	 * station hwaddr for individual keys. aid of the station is given
	 * to help low-level driver in selecting which key->hw_key_idx to use
	 * for this key. TX control data will use the hw_key_idx selected by
	 * the low-level driver. */
	/*
	 * Set encryption key.
	 *
	 * 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.
	 * When transmitting, the TX control data will use the hw_key_idx
	 * selected by the low-level driver.
	 */
	int (*set_key)(struct ieee80211_hw *hw, set_key_cmd cmd,
		       u8 *addr, struct ieee80211_key_conf *key, int aid);
		       u8 *address, struct ieee80211_key_conf *key,
		       int static_wep_only);

	/* Set TX key index for default/broadcast keys. This is needed in cases
	/*
	 * Set TX key index for default/broadcast keys. This is needed in cases
	 * where wlan card is doing full WEP/TKIP encapsulation (wep_include_iv
	 * 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. */
	 * index for each TX frame.
	 */
	int (*set_key_idx)(struct ieee80211_hw *hw, int idx);

	/* Enable/disable IEEE 802.1X. This item requests wlan card to pass
+32 −17
Original line number Diff line number Diff line
@@ -14,17 +14,17 @@
#include "debugfs.h"
#include "debugfs_key.h"

#define KEY_READ(name, buflen, format_string)				\
#define KEY_READ(name, prop, buflen, format_string)			\
static ssize_t key_##name##_read(struct file *file,			\
				 char __user *userbuf,			\
				 size_t count, loff_t *ppos)		\
{									\
	char buf[buflen];						\
	struct ieee80211_key *key = file->private_data;			\
	int res = scnprintf(buf, buflen, format_string, key->name);	\
	int res = scnprintf(buf, buflen, format_string, key->prop);	\
	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
}
#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
#define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n")

#define KEY_OPS(name)							\
static const struct file_operations key_ ##name## _ops = {		\
@@ -36,10 +36,25 @@ static const struct file_operations key_ ##name## _ops = { \
		 KEY_READ_##format(name)				\
		 KEY_OPS(name)

KEY_FILE(keylen, D);
KEY_FILE(force_sw_encrypt, D);
KEY_FILE(keyidx, D);
KEY_FILE(hw_key_idx, D);
#define KEY_CONF_READ(name, buflen, format_string)			\
	KEY_READ(conf_##name, conf.name, buflen, format_string)
#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n")
#define KEY_CONF_READ_X(name) KEY_CONF_READ(name, 20, "0x%x\n")

#define KEY_CONF_OPS(name)						\
static const struct file_operations key_ ##name## _ops = {		\
	.read = key_conf_##name##_read,					\
	.open = mac80211_open_file_generic,				\
}

#define KEY_CONF_FILE(name, format)					\
		 KEY_CONF_READ_##format(name)				\
		 KEY_CONF_OPS(name)

KEY_CONF_FILE(keylen, D);
KEY_CONF_FILE(keyidx, D);
KEY_CONF_FILE(hw_key_idx, D);
KEY_CONF_FILE(flags, X);
KEY_FILE(tx_rx_count, D);

static ssize_t key_algorithm_read(struct file *file,
@@ -49,7 +64,7 @@ static ssize_t key_algorithm_read(struct file *file,
	char *alg;
	struct ieee80211_key *key = file->private_data;

	switch (key->alg) {
	switch (key->conf.alg) {
	case ALG_WEP:
		alg = "WEP\n";
		break;
@@ -74,7 +89,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
	int len;
	struct ieee80211_key *key = file->private_data;

	switch (key->alg) {
	switch (key->conf.alg) {
	case ALG_WEP:
		len = scnprintf(buf, sizeof(buf), "\n");
		break;
@@ -103,7 +118,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
	int i, len;
	const u8 *rpn;

	switch (key->alg) {
	switch (key->conf.alg) {
	case ALG_WEP:
		len = scnprintf(buf, sizeof(buf), "\n");
		break;
@@ -139,7 +154,7 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
	char buf[20];
	int len;

	if (key->alg != ALG_CCMP)
	if (key->conf.alg != ALG_CCMP)
		return 0;
	len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
@@ -150,12 +165,12 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf,
			    size_t count, loff_t *ppos)
{
	struct ieee80211_key *key = file->private_data;
	int i, res, bufsize = 2*key->keylen+2;
	int i, res, bufsize = 2 * key->conf.keylen + 2;
	char *buf = kmalloc(bufsize, GFP_KERNEL);
	char *p = buf;

	for (i = 0; i < key->keylen; i++)
		p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
	for (i = 0; i < key->conf.keylen; i++)
		p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
	p += scnprintf(p, bufsize+buf-p, "\n");
	res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
	kfree(buf);
@@ -185,7 +200,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_local *local,
		return;

	DEBUGFS_ADD(keylen);
	DEBUGFS_ADD(force_sw_encrypt);
	DEBUGFS_ADD(flags);
	DEBUGFS_ADD(keyidx);
	DEBUGFS_ADD(hw_key_idx);
	DEBUGFS_ADD(tx_rx_count);
@@ -205,7 +220,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
		return;

	DEBUGFS_DEL(keylen);
	DEBUGFS_DEL(force_sw_encrypt);
	DEBUGFS_DEL(flags);
	DEBUGFS_DEL(keyidx);
	DEBUGFS_DEL(hw_key_idx);
	DEBUGFS_DEL(tx_rx_count);
@@ -227,7 +242,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
	if (!sdata->debugfsdir)
		return;

	sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
	sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx);
	sdata->debugfs.default_key =
		debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
}
+3 −2
Original line number Diff line number Diff line
@@ -890,7 +890,7 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
	if (!key)
		goto no_key;

	switch (key->alg) {
	switch (key->conf.alg) {
	case ALG_WEP:
		iv_len = WEP_IV_LEN;
		mic_len = WEP_ICV_LEN;
@@ -907,7 +907,8 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
		goto no_key;
	}

	if (skb->len >= mic_len && key->force_sw_encrypt)
	if (skb->len >= mic_len &&
	    (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT))
		skb_trim(skb, skb->len - mic_len);
	if (skb->len >= iv_len && skb->len > hdrlen) {
		memmove(skb->data + iv_len, skb->data, hdrlen);
+0 −3
Original line number Diff line number Diff line
@@ -816,9 +816,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);

/* key handling */
struct ieee80211_key_conf *
ieee80211_key_data2conf(struct ieee80211_local *local,
			const struct ieee80211_key *data);
struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
					  int idx, size_t key_len, gfp_t flags);
void ieee80211_key_free(struct ieee80211_key *key);
+2 −1
Original line number Diff line number Diff line
@@ -227,7 +227,8 @@ void ieee80211_if_reinit(struct net_device *dev)
		memset(addr, 0xff, ETH_ALEN);
		if (local->ops->set_key)
			local->ops->set_key(local_to_hw(local), DISABLE_KEY, addr,
					    local->keys[i], 0);
					    local->keys[i],
					    local->default_wep_only);
#endif
		ieee80211_key_free(sdata->keys[i]);
		sdata->keys[i] = NULL;
Loading