Skip to content

Commit

Permalink
mac80211: 802.11w - Use BIP (AES-128-CMAC)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jouni Malinen authored and John W. Linville committed Jan 29, 2009
1 parent 765cb46 commit 3cfcf6a
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 21 deletions.
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath5k/pcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key)
return AR5K_KEYTABLE_TYPE_40;
else if (key->keylen == LEN_WEP104)
return AR5K_KEYTABLE_TYPE_104;
return -EINVAL;
default:
return -EINVAL;
}
return -EINVAL;
}
Expand Down
1 change: 1 addition & 0 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,7 @@ enum ieee80211_back_parties {
/* reserved: 0x000FAC03 */
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06

#define WLAN_MAX_KEY_LEN 32

Expand Down
6 changes: 4 additions & 2 deletions include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
*
* @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
* by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
* @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT or
* %NL80211_ATTR_KEY_THRESHOLD.
* @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
* %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
* @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
* %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER
* attributes.
Expand Down Expand Up @@ -346,6 +346,8 @@ enum nl80211_attrs {
NL80211_ATTR_WIPHY_FREQ,
NL80211_ATTR_WIPHY_CHANNEL_TYPE,

NL80211_ATTR_KEY_DEFAULT_MGMT,

/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
Expand Down
5 changes: 5 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ struct ieee80211_channel;
*
* @set_default_key: set the default key on an interface
*
* @set_default_mgmt_key: set the default management frame key on an interface
*
* @add_beacon: Add a beacon with given parameters, @head, @interval
* and @dtim_period will be valid, @tail is optional.
* @set_beacon: Change the beacon parameters for an access point mode
Expand Down Expand Up @@ -520,6 +522,9 @@ struct cfg80211_ops {
int (*set_default_key)(struct wiphy *wiphy,
struct net_device *netdev,
u8 key_index);
int (*set_default_mgmt_key)(struct wiphy *wiphy,
struct net_device *netdev,
u8 key_index);

int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev,
struct beacon_parameters *info);
Expand Down
2 changes: 2 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,11 +651,13 @@ struct ieee80211_if_conf {
* @ALG_WEP: WEP40 or WEP104
* @ALG_TKIP: TKIP
* @ALG_CCMP: CCMP (AES)
* @ALG_AES_CMAC: AES-128-CMAC
*/
enum ieee80211_key_alg {
ALG_WEP,
ALG_TKIP,
ALG_CCMP,
ALG_AES_CMAC,
};

/**
Expand Down
31 changes: 31 additions & 0 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
case WLAN_CIPHER_SUITE_CCMP:
alg = ALG_CCMP;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
alg = ALG_AES_CMAC;
break;
default:
return -EINVAL;
}
Expand Down Expand Up @@ -275,6 +278,17 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
else
params.cipher = WLAN_CIPHER_SUITE_WEP104;
break;
case ALG_AES_CMAC:
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
seq[0] = key->u.aes_cmac.tx_pn[5];
seq[1] = key->u.aes_cmac.tx_pn[4];
seq[2] = key->u.aes_cmac.tx_pn[3];
seq[3] = key->u.aes_cmac.tx_pn[2];
seq[4] = key->u.aes_cmac.tx_pn[1];
seq[5] = key->u.aes_cmac.tx_pn[0];
params.seq = seq;
params.seq_len = 6;
break;
}

params.key = key->conf.key;
Expand Down Expand Up @@ -304,6 +318,22 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
return 0;
}

static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx)
{
struct ieee80211_sub_if_data *sdata;

rcu_read_lock();

sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_set_default_mgmt_key(sdata, key_idx);

rcu_read_unlock();

return 0;
}

static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
Expand Down Expand Up @@ -1153,6 +1183,7 @@ struct cfg80211_ops mac80211_config_ops = {
.del_key = ieee80211_del_key,
.get_key = ieee80211_get_key,
.set_default_key = ieee80211_config_default_key,
.set_default_mgmt_key = ieee80211_config_default_mgmt_key,
.add_beacon = ieee80211_add_beacon,
.set_beacon = ieee80211_set_beacon,
.del_beacon = ieee80211_del_beacon,
Expand Down
79 changes: 77 additions & 2 deletions net/mac80211/debugfs_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ static ssize_t key_algorithm_read(struct file *file,
case ALG_CCMP:
alg = "CCMP\n";
break;
case ALG_AES_CMAC:
alg = "AES-128-CMAC\n";
break;
default:
return 0;
}
Expand Down Expand Up @@ -105,6 +108,12 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
break;
case ALG_AES_CMAC:
tpn = key->u.aes_cmac.tx_pn;
len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
tpn[0], tpn[1], tpn[2], tpn[3], tpn[4],
tpn[5]);
break;
default:
return 0;
}
Expand Down Expand Up @@ -142,6 +151,14 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
}
len = p - buf;
break;
case ALG_AES_CMAC:
rpn = key->u.aes_cmac.rx_pn;
p += scnprintf(p, sizeof(buf)+buf-p,
"%02x%02x%02x%02x%02x%02x\n",
rpn[0], rpn[1], rpn[2],
rpn[3], rpn[4], rpn[5]);
len = p - buf;
break;
default:
return 0;
}
Expand All @@ -156,13 +173,40 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
char buf[20];
int len;

if (key->conf.alg != ALG_CCMP)
switch (key->conf.alg) {
case ALG_CCMP:
len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
break;
case ALG_AES_CMAC:
len = scnprintf(buf, sizeof(buf), "%u\n",
key->u.aes_cmac.replays);
break;
default:
return 0;
len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
}
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
KEY_OPS(replays);

static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_key *key = file->private_data;
char buf[20];
int len;

switch (key->conf.alg) {
case ALG_AES_CMAC:
len = scnprintf(buf, sizeof(buf), "%u\n",
key->u.aes_cmac.icverrors);
break;
default:
return 0;
}
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
KEY_OPS(icverrors);

static ssize_t key_key_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
Expand Down Expand Up @@ -222,6 +266,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
DEBUGFS_ADD(tx_spec);
DEBUGFS_ADD(rx_spec);
DEBUGFS_ADD(replays);
DEBUGFS_ADD(icverrors);
DEBUGFS_ADD(key);
DEBUGFS_ADD(ifindex);
};
Expand All @@ -243,6 +288,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
DEBUGFS_DEL(tx_spec);
DEBUGFS_DEL(rx_spec);
DEBUGFS_DEL(replays);
DEBUGFS_DEL(icverrors);
DEBUGFS_DEL(key);
DEBUGFS_DEL(ifindex);

Expand Down Expand Up @@ -280,6 +326,35 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
sdata->common_debugfs.default_key = NULL;
}

void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
{
char buf[50];
struct ieee80211_key *key;

if (!sdata->debugfsdir)
return;

/* this is running under the key lock */

key = sdata->default_mgmt_key;
if (key) {
sprintf(buf, "../keys/%d", key->debugfs.cnt);
sdata->common_debugfs.default_mgmt_key =
debugfs_create_symlink("default_mgmt_key",
sdata->debugfsdir, buf);
} else
ieee80211_debugfs_key_remove_mgmt_default(sdata);
}

void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata)
{
if (!sdata)
return;

debugfs_remove(sdata->common_debugfs.default_mgmt_key);
sdata->common_debugfs.default_mgmt_key = NULL;
}

void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta)
{
Expand Down
10 changes: 10 additions & 0 deletions net/mac80211/debugfs_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key);
void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_add_mgmt_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_mgmt_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta);
#else
Expand All @@ -19,6 +23,12 @@ static inline void ieee80211_debugfs_key_add_default(
static inline void ieee80211_debugfs_key_remove_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_add_mgmt_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_remove_mgmt_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta)
{}
Expand Down
5 changes: 4 additions & 1 deletion net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,10 @@ struct ieee80211_sub_if_data {
unsigned int fragment_next;

#define NUM_DEFAULT_KEYS 4
struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
#define NUM_DEFAULT_MGMT_KEYS 2
struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key *default_key;
struct ieee80211_key *default_mgmt_key;

u16 sequence_number;

Expand Down Expand Up @@ -482,6 +484,7 @@ struct ieee80211_sub_if_data {
} debugfs;
struct {
struct dentry *default_key;
struct dentry *default_mgmt_key;
} common_debugfs;

#ifdef CONFIG_MAC80211_MESH
Expand Down
Loading

0 comments on commit 3cfcf6a

Please sign in to comment.