aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h4
-rw-r--r--net/mac80211/cfg.c3
-rw-r--r--net/mac80211/key.c21
-rw-r--r--net/mac80211/key.h3
-rw-r--r--net/wireless/nl80211.c5
-rw-r--r--net/wireless/wext-compat.c5
6 files changed, 36 insertions, 5 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2781525b03d..dbea93b694e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -79,8 +79,8 @@
* @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.
+ * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
+ * and %NL80211_ATTR_KEY_SEQ attributes.
* @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
* or %NL80211_ATTR_MAC.
*
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6464bfd232c..77e9ff5ec4f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -141,7 +141,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}
- key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
+ key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key,
+ params->seq_len, params->seq);
if (!key)
return -ENOMEM;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index b7e1350273b..827ea8e6ee0 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -290,9 +290,11 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
int idx,
size_t key_len,
- const u8 *key_data)
+ const u8 *key_data,
+ size_t seq_len, const u8 *seq)
{
struct ieee80211_key *key;
+ int i, j;
BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
@@ -318,14 +320,31 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
case ALG_TKIP:
key->conf.iv_len = TKIP_IV_LEN;
key->conf.icv_len = TKIP_ICV_LEN;
+ if (seq && seq_len == 6) {
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+ key->u.tkip.rx[i].iv32 =
+ get_unaligned_le32(&seq[2]);
+ key->u.tkip.rx[i].iv16 =
+ get_unaligned_le16(seq);
+ }
+ }
break;
case ALG_CCMP:
key->conf.iv_len = CCMP_HDR_LEN;
key->conf.icv_len = CCMP_MIC_LEN;
+ if (seq && seq_len == CCMP_PN_LEN) {
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ for (j = 0; j < CCMP_PN_LEN; j++)
+ key->u.ccmp.rx_pn[i][j] =
+ seq[CCMP_PN_LEN - j - 1];
+ }
break;
case ALG_AES_CMAC:
key->conf.iv_len = 0;
key->conf.icv_len = sizeof(struct ieee80211_mmie);
+ if (seq && seq_len == 6)
+ for (j = 0; j < 6; j++)
+ key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
break;
}
memcpy(key->conf.key, key_data, key_len);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 215d3ef42a4..9572e00f532 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -144,7 +144,8 @@ struct ieee80211_key {
struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
int idx,
size_t key_len,
- const u8 *key_data);
+ const u8 *key_data,
+ size_t seq_len, const u8 *seq);
/*
* Insert a key into data structures (sdata, sta if necessary)
* to make it used, free old key.
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cad281390cf..f0fec2f4982 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1115,6 +1115,11 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
}
+ if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
+ params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
+ params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
+ }
+
if (info->attrs[NL80211_ATTR_KEY_IDX])
key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index ffc98a8d6e5..f98090b90fb 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -663,6 +663,11 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
params.key_len = ext->key_len;
params.cipher = cipher;
+ if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+ params.seq = ext->rx_seq;
+ params.seq_len = 6;
+ }
+
return cfg80211_set_encryption(
rdev, dev, addr, remove,
ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,