diff options
-rw-r--r-- | include/linux/nl80211.h | 4 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 3 | ||||
-rw-r--r-- | net/mac80211/key.c | 21 | ||||
-rw-r--r-- | net/mac80211/key.h | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 5 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 5 |
6 files changed, 36 insertions, 5 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2781525b03d5..dbea93b694e5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -79,8 +79,8 @@ | |||
79 | * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, | 79 | * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, |
80 | * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. | 80 | * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. |
81 | * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, | 81 | * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, |
82 | * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER | 82 | * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, |
83 | * attributes. | 83 | * and %NL80211_ATTR_KEY_SEQ attributes. |
84 | * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX | 84 | * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX |
85 | * or %NL80211_ATTR_MAC. | 85 | * or %NL80211_ATTR_MAC. |
86 | * | 86 | * |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6464bfd232c9..77e9ff5ec4f3 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, | |||
141 | return -EINVAL; | 141 | return -EINVAL; |
142 | } | 142 | } |
143 | 143 | ||
144 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key); | 144 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, |
145 | params->seq_len, params->seq); | ||
145 | if (!key) | 146 | if (!key) |
146 | return -ENOMEM; | 147 | return -ENOMEM; |
147 | 148 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b7e1350273bb..827ea8e6ee0a 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, | |||
290 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 290 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, |
291 | int idx, | 291 | int idx, |
292 | size_t key_len, | 292 | size_t key_len, |
293 | const u8 *key_data) | 293 | const u8 *key_data, |
294 | size_t seq_len, const u8 *seq) | ||
294 | { | 295 | { |
295 | struct ieee80211_key *key; | 296 | struct ieee80211_key *key; |
297 | int i, j; | ||
296 | 298 | ||
297 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); | 299 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
298 | 300 | ||
@@ -318,14 +320,31 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
318 | case ALG_TKIP: | 320 | case ALG_TKIP: |
319 | key->conf.iv_len = TKIP_IV_LEN; | 321 | key->conf.iv_len = TKIP_IV_LEN; |
320 | key->conf.icv_len = TKIP_ICV_LEN; | 322 | key->conf.icv_len = TKIP_ICV_LEN; |
323 | if (seq && seq_len == 6) { | ||
324 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { | ||
325 | key->u.tkip.rx[i].iv32 = | ||
326 | get_unaligned_le32(&seq[2]); | ||
327 | key->u.tkip.rx[i].iv16 = | ||
328 | get_unaligned_le16(seq); | ||
329 | } | ||
330 | } | ||
321 | break; | 331 | break; |
322 | case ALG_CCMP: | 332 | case ALG_CCMP: |
323 | key->conf.iv_len = CCMP_HDR_LEN; | 333 | key->conf.iv_len = CCMP_HDR_LEN; |
324 | key->conf.icv_len = CCMP_MIC_LEN; | 334 | key->conf.icv_len = CCMP_MIC_LEN; |
335 | if (seq && seq_len == CCMP_PN_LEN) { | ||
336 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | ||
337 | for (j = 0; j < CCMP_PN_LEN; j++) | ||
338 | key->u.ccmp.rx_pn[i][j] = | ||
339 | seq[CCMP_PN_LEN - j - 1]; | ||
340 | } | ||
325 | break; | 341 | break; |
326 | case ALG_AES_CMAC: | 342 | case ALG_AES_CMAC: |
327 | key->conf.iv_len = 0; | 343 | key->conf.iv_len = 0; |
328 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | 344 | key->conf.icv_len = sizeof(struct ieee80211_mmie); |
345 | if (seq && seq_len == 6) | ||
346 | for (j = 0; j < 6; j++) | ||
347 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
329 | break; | 348 | break; |
330 | } | 349 | } |
331 | memcpy(key->conf.key, key_data, key_len); | 350 | memcpy(key->conf.key, key_data, key_len); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 215d3ef42a4f..9572e00f532c 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -144,7 +144,8 @@ struct ieee80211_key { | |||
144 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 144 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, |
145 | int idx, | 145 | int idx, |
146 | size_t key_len, | 146 | size_t key_len, |
147 | const u8 *key_data); | 147 | const u8 *key_data, |
148 | size_t seq_len, const u8 *seq); | ||
148 | /* | 149 | /* |
149 | * Insert a key into data structures (sdata, sta if necessary) | 150 | * Insert a key into data structures (sdata, sta if necessary) |
150 | * to make it used, free old key. | 151 | * to make it used, free old key. |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cad281390cfa..f0fec2f49828 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) | |||
1115 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); | 1115 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | if (info->attrs[NL80211_ATTR_KEY_SEQ]) { | ||
1119 | params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
1120 | params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
1121 | } | ||
1122 | |||
1118 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 1123 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
1119 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 1124 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
1120 | 1125 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index ffc98a8d6e5c..f98090b90fbf 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, | |||
663 | params.key_len = ext->key_len; | 663 | params.key_len = ext->key_len; |
664 | params.cipher = cipher; | 664 | params.cipher = cipher; |
665 | 665 | ||
666 | if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { | ||
667 | params.seq = ext->rx_seq; | ||
668 | params.seq_len = 6; | ||
669 | } | ||
670 | |||
666 | return cfg80211_set_encryption( | 671 | return cfg80211_set_encryption( |
667 | rdev, dev, addr, remove, | 672 | rdev, dev, addr, remove, |
668 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, | 673 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, |