aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-05-11 14:57:58 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-13 15:44:39 -0400
commitfaa8fdc85347cc76d87b43ea718785661c54f656 (patch)
treed6a2bad74310885e8f0836791c93070d243b6b2c
parent3f77316c6b99f596bfbf72c0542f47f7230b702e (diff)
nl80211: Add RSC configuration for new keys
When setting a key with NL80211_CMD_NEW_KEY, we should allow the key sequence number (RSC) to be set in order to allow replay protection to work correctly for group keys. This patch documents this use for nl80211 and adds the couple of missing pieces in nl80211/cfg80211 and mac80211 to support this. In addition, WEXT SIOCSIWENCODEEXT compat processing in cfg80211 is extended to handle the RSC (this was already specified in WEXT, but just not implemented in cfg80211/mac80211). Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-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 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,
290struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, 290struct 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 {
144struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, 144struct 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,