2007-05-06 01:45:53 +07:00
|
|
|
/*
|
|
|
|
* Copyright 2002-2004, Instant802 Networks, Inc.
|
|
|
|
* Copyright 2005, Devicescape Software, Inc.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef IEEE80211_KEY_H
|
|
|
|
#define IEEE80211_KEY_H
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
2007-08-29 04:01:54 +07:00
|
|
|
#include <linux/list.h>
|
2007-05-06 01:45:53 +07:00
|
|
|
#include <linux/crypto.h>
|
2008-02-25 22:27:45 +07:00
|
|
|
#include <linux/rcupdate.h>
|
2007-05-06 01:45:53 +07:00
|
|
|
#include <net/mac80211.h>
|
|
|
|
|
2010-10-06 00:39:30 +07:00
|
|
|
#define NUM_DEFAULT_KEYS 4
|
|
|
|
#define NUM_DEFAULT_MGMT_KEYS 2
|
2013-03-24 19:23:27 +07:00
|
|
|
#define MAX_PN_LEN 16
|
2010-10-06 00:39:30 +07:00
|
|
|
|
2007-08-29 04:01:55 +07:00
|
|
|
struct ieee80211_local;
|
|
|
|
struct ieee80211_sub_if_data;
|
|
|
|
struct sta_info;
|
|
|
|
|
2008-02-25 22:27:45 +07:00
|
|
|
/**
|
|
|
|
* enum ieee80211_internal_key_flags - internal key flags
|
|
|
|
*
|
|
|
|
* @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
|
|
|
|
* in the hardware for TX crypto hardware acceleration.
|
2011-07-12 17:30:59 +07:00
|
|
|
* @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped.
|
2015-03-17 17:47:33 +07:00
|
|
|
* @KEY_FLAG_CIPHER_SCHEME: This key is for a hardware cipher scheme
|
2008-02-25 22:27:45 +07:00
|
|
|
*/
|
|
|
|
enum ieee80211_internal_key_flags {
|
|
|
|
KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
|
2011-07-12 17:30:59 +07:00
|
|
|
KEY_FLAG_TAINTED = BIT(1),
|
2015-03-17 17:47:33 +07:00
|
|
|
KEY_FLAG_CIPHER_SCHEME = BIT(2),
|
2008-02-25 22:27:45 +07:00
|
|
|
};
|
2007-08-29 04:01:55 +07:00
|
|
|
|
2009-12-10 05:25:05 +07:00
|
|
|
enum ieee80211_internal_tkip_state {
|
|
|
|
TKIP_STATE_NOT_INIT,
|
|
|
|
TKIP_STATE_PHASE1_DONE,
|
|
|
|
TKIP_STATE_PHASE1_HW_UPLOADED,
|
|
|
|
};
|
|
|
|
|
2008-05-15 06:26:19 +07:00
|
|
|
struct tkip_ctx {
|
mac80211: fix TKIP races, make API easier to use
Our current TKIP code races against itself on TX
since we can process multiple packets at the same
time on different ACs, but they all share the TX
context for TKIP. This can lead to bad IVs etc.
Also, the crypto offload helper code just obtains
the P1K/P2K from the cache, and can update it as
well, but there's no guarantee that packets are
really processed in order.
To fix these issues, first introduce a spinlock
that will protect the IV16/IV32 values in the TX
context. This first step makes sure that we don't
assign the same IV multiple times or get confused
in other ways.
Secondly, change the way the P1K cache works. I
add a field "p1k_iv32" that stores the value of
the IV32 when the P1K was last recomputed, and
if different from the last time, then a new P1K
is recomputed. This can cause the P1K computation
to flip back and forth if packets are processed
out of order. All this also happens under the new
spinlock.
Finally, because there are argument differences,
split up the ieee80211_get_tkip_key() API into
ieee80211_get_tkip_p1k() and ieee80211_get_tkip_p2k()
and give them the correct arguments.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-07-08 03:28:01 +07:00
|
|
|
u32 iv32; /* current iv32 */
|
|
|
|
u16 iv16; /* current iv16 */
|
|
|
|
u16 p1k[5]; /* p1k cache */
|
|
|
|
u32 p1k_iv32; /* iv32 for which p1k computed */
|
2009-12-10 05:25:05 +07:00
|
|
|
enum ieee80211_internal_tkip_state state;
|
2008-05-15 06:26:19 +07:00
|
|
|
};
|
|
|
|
|
2007-05-06 01:45:53 +07:00
|
|
|
struct ieee80211_key {
|
2007-08-29 04:01:55 +07:00
|
|
|
struct ieee80211_local *local;
|
|
|
|
struct ieee80211_sub_if_data *sdata;
|
|
|
|
struct sta_info *sta;
|
|
|
|
|
2008-04-08 22:56:52 +07:00
|
|
|
/* for sdata list */
|
2007-08-29 04:01:55 +07:00
|
|
|
struct list_head list;
|
|
|
|
|
2010-06-01 15:19:19 +07:00
|
|
|
/* protected by key mutex */
|
2007-08-29 04:01:55 +07:00
|
|
|
unsigned int flags;
|
|
|
|
|
2007-05-06 01:45:53 +07:00
|
|
|
union {
|
|
|
|
struct {
|
mac80211: fix TKIP races, make API easier to use
Our current TKIP code races against itself on TX
since we can process multiple packets at the same
time on different ACs, but they all share the TX
context for TKIP. This can lead to bad IVs etc.
Also, the crypto offload helper code just obtains
the P1K/P2K from the cache, and can update it as
well, but there's no guarantee that packets are
really processed in order.
To fix these issues, first introduce a spinlock
that will protect the IV16/IV32 values in the TX
context. This first step makes sure that we don't
assign the same IV multiple times or get confused
in other ways.
Secondly, change the way the P1K cache works. I
add a field "p1k_iv32" that stores the value of
the IV32 when the P1K was last recomputed, and
if different from the last time, then a new P1K
is recomputed. This can cause the P1K computation
to flip back and forth if packets are processed
out of order. All this also happens under the new
spinlock.
Finally, because there are argument differences,
split up the ieee80211_get_tkip_key() API into
ieee80211_get_tkip_p1k() and ieee80211_get_tkip_p2k()
and give them the correct arguments.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-07-08 03:28:01 +07:00
|
|
|
/* protects tx context */
|
|
|
|
spinlock_t txlock;
|
|
|
|
|
2007-05-06 01:45:53 +07:00
|
|
|
/* last used TSC */
|
2008-05-15 06:26:19 +07:00
|
|
|
struct tkip_ctx tx;
|
2007-05-06 01:45:53 +07:00
|
|
|
|
|
|
|
/* last received RSC */
|
2012-11-15 05:22:21 +07:00
|
|
|
struct tkip_ctx rx[IEEE80211_NUM_TIDS];
|
2012-12-04 21:17:42 +07:00
|
|
|
|
|
|
|
/* number of mic failures */
|
|
|
|
u32 mic_failures;
|
2007-05-06 01:45:53 +07:00
|
|
|
} tkip;
|
|
|
|
struct {
|
2011-07-07 02:59:39 +07:00
|
|
|
atomic64_t tx_pn;
|
2010-06-12 00:27:33 +07:00
|
|
|
/*
|
|
|
|
* Last received packet number. The first
|
2012-11-15 05:22:21 +07:00
|
|
|
* IEEE80211_NUM_TIDS counters are used with Data
|
2010-06-12 00:27:33 +07:00
|
|
|
* frames and the last counter is used with Robust
|
|
|
|
* Management frames.
|
|
|
|
*/
|
2013-05-08 18:09:08 +07:00
|
|
|
u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
|
2013-10-10 14:55:20 +07:00
|
|
|
struct crypto_aead *tfm;
|
2007-05-06 01:45:53 +07:00
|
|
|
u32 replays; /* dot11RSNAStatsCCMPReplays */
|
|
|
|
} ccmp;
|
2009-01-08 18:32:01 +07:00
|
|
|
struct {
|
2011-07-07 03:00:35 +07:00
|
|
|
atomic64_t tx_pn;
|
2013-05-08 18:09:08 +07:00
|
|
|
u8 rx_pn[IEEE80211_CMAC_PN_LEN];
|
2009-01-08 18:32:01 +07:00
|
|
|
struct crypto_cipher *tfm;
|
|
|
|
u32 replays; /* dot11RSNAStatsCMACReplays */
|
|
|
|
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
|
|
|
|
} aes_cmac;
|
2015-01-25 00:52:09 +07:00
|
|
|
struct {
|
|
|
|
atomic64_t tx_pn;
|
|
|
|
u8 rx_pn[IEEE80211_GMAC_PN_LEN];
|
|
|
|
struct crypto_aead *tfm;
|
|
|
|
u32 replays; /* dot11RSNAStatsCMACReplays */
|
|
|
|
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
|
|
|
|
} aes_gmac;
|
2015-01-25 00:52:06 +07:00
|
|
|
struct {
|
|
|
|
atomic64_t tx_pn;
|
|
|
|
/* Last received packet number. The first
|
|
|
|
* IEEE80211_NUM_TIDS counters are used with Data
|
|
|
|
* frames and the last counter is used with Robust
|
|
|
|
* Management frames.
|
|
|
|
*/
|
|
|
|
u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_GCMP_PN_LEN];
|
|
|
|
struct crypto_aead *tfm;
|
|
|
|
u32 replays; /* dot11RSNAStatsGCMPReplays */
|
|
|
|
} gcmp;
|
2013-03-24 19:23:27 +07:00
|
|
|
struct {
|
|
|
|
/* generic cipher scheme */
|
|
|
|
u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN];
|
|
|
|
} gen;
|
2007-05-06 01:45:53 +07:00
|
|
|
} u;
|
|
|
|
|
2007-08-29 04:01:54 +07:00
|
|
|
/* number of times this key has been used */
|
|
|
|
int tx_rx_count;
|
2007-05-06 01:45:53 +07:00
|
|
|
|
2007-05-06 01:46:38 +07:00
|
|
|
#ifdef CONFIG_MAC80211_DEBUGFS
|
|
|
|
struct {
|
|
|
|
struct dentry *stalink;
|
|
|
|
struct dentry *dir;
|
2008-04-09 03:46:36 +07:00
|
|
|
int cnt;
|
2007-05-06 01:46:38 +07:00
|
|
|
} debugfs;
|
|
|
|
#endif
|
|
|
|
|
2007-08-29 04:01:54 +07:00
|
|
|
/*
|
|
|
|
* key config, must be last because it contains key
|
|
|
|
* material as variable length member
|
|
|
|
*/
|
|
|
|
struct ieee80211_key_conf conf;
|
2007-05-06 01:45:53 +07:00
|
|
|
};
|
|
|
|
|
2013-03-24 19:23:27 +07:00
|
|
|
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);
|
2008-02-25 22:27:45 +07:00
|
|
|
/*
|
|
|
|
* Insert a key into data structures (sdata, sta if necessary)
|
2013-03-07 04:53:52 +07:00
|
|
|
* to make it used, free old key. On failure, also free the new key.
|
2008-02-25 22:27:45 +07:00
|
|
|
*/
|
2013-03-07 04:53:52 +07:00
|
|
|
int ieee80211_key_link(struct ieee80211_key *key,
|
|
|
|
struct ieee80211_sub_if_data *sdata,
|
|
|
|
struct sta_info *sta);
|
2013-03-07 04:58:23 +07:00
|
|
|
void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
|
2013-03-07 04:53:52 +07:00
|
|
|
void ieee80211_key_free_unused(struct ieee80211_key *key);
|
2010-12-10 01:49:02 +07:00
|
|
|
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
|
|
|
|
bool uni, bool multi);
|
2009-01-08 18:32:02 +07:00
|
|
|
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
|
|
|
|
int idx);
|
2013-12-05 05:47:09 +07:00
|
|
|
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
|
|
|
|
bool force_synchronize);
|
2013-03-07 05:09:11 +07:00
|
|
|
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
|
|
|
struct sta_info *sta);
|
2007-08-29 04:01:55 +07:00
|
|
|
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
|
|
|
|
|
2011-05-13 19:15:49 +07:00
|
|
|
#define key_mtx_dereference(local, ref) \
|
|
|
|
rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
|
|
|
|
|
mac80211: defer tailroom counter manipulation when roaming
During roaming, the crypto_tx_tailroom_needed_cnt counter
will often take values 2,1,0,1,2 because first keys are
removed and then new keys are added. This is inefficient
because during the 0->1 transition, synchronize_net must
be called to avoid packet races, although typically no
packets would be flowing during that time.
To avoid that, defer the decrement (2->1, 1->0) when keys
are removed (by half a second). This means the counter
will really have the values 2,2,2,3,4 ... 2, thus never
reaching 0 and having to do the 0->1 transition.
Note that this patch entirely disregards the drivers for
which this optimisation was done to start with, for them
the key removal itself will be expensive because it has
to synchronize_net() after the counter is incremented to
remove the key from HW crypto. For them the sequence will
look like this: 0,1,0,1,0,1,0,1,0 (*) which is clearly a
lot more inefficient. This could be addressed separately,
during key removal the 0->1->0 sequence isn't necessary.
(*) it starts at 0 because HW crypto is on, then goes to
1 when HW crypto is disabled for a key, then back to
0 because the key is deleted; this happens for both
keys in the example. When new keys are added, it goes
to 1 first because they're added in software; when a
key is moved to hardware it goes back to 0
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2013-02-23 06:59:03 +07:00
|
|
|
void ieee80211_delayed_tailroom_dec(struct work_struct *wk);
|
|
|
|
|
2007-05-06 01:45:53 +07:00
|
|
|
#endif /* IEEE80211_KEY_H */
|