summaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
authorMax Stepanov <Max.Stepanov@intel.com>2013-03-24 14:23:27 +0200
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 20:50:52 +0100
commit2475b1cc0d5283a33144b79f3eba6d401d873962 (patch)
tree5933a46b04abf495b18877ce710f84a4acda2841 /net/mac80211/key.c
parent6bc54fbcee6836f08355fcca76549c22ad2c2940 (diff)
downloadlinux-2475b1cc0d5283a33144b79f3eba6d401d873962.tar.gz
linux-2475b1cc0d5283a33144b79f3eba6d401d873962.tar.bz2
linux-2475b1cc0d5283a33144b79f3eba6d401d873962.zip
mac80211: add generic cipher scheme support
This adds generic cipher scheme support to mac80211, such schemes are fully under control by the driver. On hw registration drivers may specify additional HW ciphers with a scheme how these ciphers have to be handled by mac80211 TX/RR. A cipher scheme specifies a cipher suite value, a size of the security header to be added to or stripped from frames and how the PN is to be verified on RX. Signed-off-by: Max Stepanov <Max.Stepanov@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ab8468047200..e568d98167d0 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -267,22 +267,22 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
if (new)
list_add_tail(&new->list, &sdata->key_list);
- if (sta && pairwise) {
- rcu_assign_pointer(sta->ptk, new);
- } else if (sta) {
- if (old)
- idx = old->conf.keyidx;
- else
- idx = new->conf.keyidx;
- rcu_assign_pointer(sta->gtk[idx], new);
- } else {
- WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
+ WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
- if (old)
- idx = old->conf.keyidx;
- else
- idx = new->conf.keyidx;
+ if (old)
+ idx = old->conf.keyidx;
+ else
+ idx = new->conf.keyidx;
+ if (sta) {
+ if (pairwise) {
+ rcu_assign_pointer(sta->ptk[idx], new);
+ sta->ptk_idx = idx;
+ } else {
+ rcu_assign_pointer(sta->gtk[idx], new);
+ sta->gtk_idx = idx;
+ }
+ } else {
defunikey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_unicast_key);
@@ -316,9 +316,11 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
list_del(&old->list);
}
-struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
- const u8 *key_data,
- size_t seq_len, const u8 *seq)
+struct ieee80211_key *
+ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
+ const u8 *key_data,
+ size_t seq_len, const u8 *seq,
+ const struct ieee80211_cipher_scheme *cs)
{
struct ieee80211_key *key;
int i, j, err;
@@ -397,6 +399,18 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
return ERR_PTR(err);
}
break;
+ default:
+ if (cs) {
+ size_t len = (seq_len > MAX_PN_LEN) ?
+ MAX_PN_LEN : seq_len;
+
+ key->conf.iv_len = cs->hdr_len;
+ key->conf.icv_len = cs->mic_len;
+ for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
+ for (j = 0; j < len; j++)
+ key->u.gen.rx_pn[i][j] =
+ seq[len - j - 1];
+ }
}
memcpy(key->conf.key, key_data, key_len);
INIT_LIST_HEAD(&key->list);
@@ -479,7 +493,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
mutex_lock(&sdata->local->key_mtx);
if (sta && pairwise)
- old_key = key_mtx_dereference(sdata->local, sta->ptk);
+ old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
else if (sta)
old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
else
@@ -629,8 +643,10 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
list_add(&key->list, &keys);
}
- key = key_mtx_dereference(local, sta->ptk);
- if (key) {
+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+ key = key_mtx_dereference(local, sta->ptk[i]);
+ if (!key)
+ continue;
ieee80211_key_replace(key->sdata, key->sta,
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
key, NULL);
@@ -881,7 +897,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
keyconf->keylen, keyconf->key,
- 0, NULL);
+ 0, NULL, NULL);
if (IS_ERR(key))
return ERR_CAST(key);