diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-07-15 10:05:24 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-07-15 10:05:24 -0400 |
commit | 95a943c162d74b20d869917bdf5df11293c35b63 (patch) | |
tree | c69d5cb97a4d97b6062a276ecdfa8582535193af /net/mac80211 | |
parent | ecae42d37045ec71831d0e0e493e00b0e0732edd (diff) | |
parent | 95acac61ba66c4abd40e038dae8c1ed2e176c7b1 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
net/bluetooth/l2cap_core.c
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/aes_ccm.c | 37 | ||||
-rw-r--r-- | net/mac80211/aes_ccm.h | 2 | ||||
-rw-r--r-- | net/mac80211/aes_cmac.c | 10 | ||||
-rw-r--r-- | net/mac80211/aes_cmac.h | 2 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 27 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.c | 13 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 8 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 46 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 27 | ||||
-rw-r--r-- | net/mac80211/iface.c | 7 | ||||
-rw-r--r-- | net/mac80211/key.c | 75 | ||||
-rw-r--r-- | net/mac80211/key.h | 32 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 58 | ||||
-rw-r--r-- | net/mac80211/rx.c | 36 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 3 | ||||
-rw-r--r-- | net/mac80211/tkip.c | 108 | ||||
-rw-r--r-- | net/mac80211/tkip.h | 8 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/util.c | 67 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 94 |
20 files changed, 477 insertions, 186 deletions
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index b9b595c08112..0785e95c9924 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <crypto/aes.h> | ||
14 | 15 | ||
15 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
16 | #include "key.h" | 17 | #include "key.h" |
@@ -21,21 +22,21 @@ static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a) | |||
21 | int i; | 22 | int i; |
22 | u8 *b_0, *aad, *b, *s_0; | 23 | u8 *b_0, *aad, *b, *s_0; |
23 | 24 | ||
24 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 25 | b_0 = scratch + 3 * AES_BLOCK_SIZE; |
25 | aad = scratch + 4 * AES_BLOCK_LEN; | 26 | aad = scratch + 4 * AES_BLOCK_SIZE; |
26 | b = scratch; | 27 | b = scratch; |
27 | s_0 = scratch + AES_BLOCK_LEN; | 28 | s_0 = scratch + AES_BLOCK_SIZE; |
28 | 29 | ||
29 | crypto_cipher_encrypt_one(tfm, b, b_0); | 30 | crypto_cipher_encrypt_one(tfm, b, b_0); |
30 | 31 | ||
31 | /* Extra Authenticate-only data (always two AES blocks) */ | 32 | /* Extra Authenticate-only data (always two AES blocks) */ |
32 | for (i = 0; i < AES_BLOCK_LEN; i++) | 33 | for (i = 0; i < AES_BLOCK_SIZE; i++) |
33 | aad[i] ^= b[i]; | 34 | aad[i] ^= b[i]; |
34 | crypto_cipher_encrypt_one(tfm, b, aad); | 35 | crypto_cipher_encrypt_one(tfm, b, aad); |
35 | 36 | ||
36 | aad += AES_BLOCK_LEN; | 37 | aad += AES_BLOCK_SIZE; |
37 | 38 | ||
38 | for (i = 0; i < AES_BLOCK_LEN; i++) | 39 | for (i = 0; i < AES_BLOCK_SIZE; i++) |
39 | aad[i] ^= b[i]; | 40 | aad[i] ^= b[i]; |
40 | crypto_cipher_encrypt_one(tfm, a, aad); | 41 | crypto_cipher_encrypt_one(tfm, a, aad); |
41 | 42 | ||
@@ -57,12 +58,12 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
57 | u8 *pos, *cpos, *b, *s_0, *e, *b_0; | 58 | u8 *pos, *cpos, *b, *s_0, *e, *b_0; |
58 | 59 | ||
59 | b = scratch; | 60 | b = scratch; |
60 | s_0 = scratch + AES_BLOCK_LEN; | 61 | s_0 = scratch + AES_BLOCK_SIZE; |
61 | e = scratch + 2 * AES_BLOCK_LEN; | 62 | e = scratch + 2 * AES_BLOCK_SIZE; |
62 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 63 | b_0 = scratch + 3 * AES_BLOCK_SIZE; |
63 | 64 | ||
64 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 65 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); |
65 | last_len = data_len % AES_BLOCK_LEN; | 66 | last_len = data_len % AES_BLOCK_SIZE; |
66 | aes_ccm_prepare(tfm, scratch, b); | 67 | aes_ccm_prepare(tfm, scratch, b); |
67 | 68 | ||
68 | /* Process payload blocks */ | 69 | /* Process payload blocks */ |
@@ -70,7 +71,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
70 | cpos = cdata; | 71 | cpos = cdata; |
71 | for (j = 1; j <= num_blocks; j++) { | 72 | for (j = 1; j <= num_blocks; j++) { |
72 | int blen = (j == num_blocks && last_len) ? | 73 | int blen = (j == num_blocks && last_len) ? |
73 | last_len : AES_BLOCK_LEN; | 74 | last_len : AES_BLOCK_SIZE; |
74 | 75 | ||
75 | /* Authentication followed by encryption */ | 76 | /* Authentication followed by encryption */ |
76 | for (i = 0; i < blen; i++) | 77 | for (i = 0; i < blen; i++) |
@@ -96,12 +97,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
96 | u8 *pos, *cpos, *b, *s_0, *a, *b_0; | 97 | u8 *pos, *cpos, *b, *s_0, *a, *b_0; |
97 | 98 | ||
98 | b = scratch; | 99 | b = scratch; |
99 | s_0 = scratch + AES_BLOCK_LEN; | 100 | s_0 = scratch + AES_BLOCK_SIZE; |
100 | a = scratch + 2 * AES_BLOCK_LEN; | 101 | a = scratch + 2 * AES_BLOCK_SIZE; |
101 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 102 | b_0 = scratch + 3 * AES_BLOCK_SIZE; |
102 | 103 | ||
103 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 104 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); |
104 | last_len = data_len % AES_BLOCK_LEN; | 105 | last_len = data_len % AES_BLOCK_SIZE; |
105 | aes_ccm_prepare(tfm, scratch, a); | 106 | aes_ccm_prepare(tfm, scratch, a); |
106 | 107 | ||
107 | /* Process payload blocks */ | 108 | /* Process payload blocks */ |
@@ -109,7 +110,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
109 | pos = data; | 110 | pos = data; |
110 | for (j = 1; j <= num_blocks; j++) { | 111 | for (j = 1; j <= num_blocks; j++) { |
111 | int blen = (j == num_blocks && last_len) ? | 112 | int blen = (j == num_blocks && last_len) ? |
112 | last_len : AES_BLOCK_LEN; | 113 | last_len : AES_BLOCK_SIZE; |
113 | 114 | ||
114 | /* Decryption followed by authentication */ | 115 | /* Decryption followed by authentication */ |
115 | b_0[14] = (j >> 8) & 0xff; | 116 | b_0[14] = (j >> 8) & 0xff; |
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 6e7820ef3448..5b7d744e2370 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h | |||
@@ -12,8 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | 14 | ||
15 | #define AES_BLOCK_LEN 16 | ||
16 | |||
17 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); | 15 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); |
18 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 16 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, |
19 | u8 *data, size_t data_len, | 17 | u8 *data, size_t data_len, |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index d502b2684a66..8dfd70d8fcfb 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -11,12 +11,12 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <crypto/aes.h> | ||
14 | 15 | ||
15 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
16 | #include "key.h" | 17 | #include "key.h" |
17 | #include "aes_cmac.h" | 18 | #include "aes_cmac.h" |
18 | 19 | ||
19 | #define AES_BLOCK_SIZE 16 | ||
20 | #define AES_CMAC_KEY_LEN 16 | 20 | #define AES_CMAC_KEY_LEN 16 |
21 | #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ | 21 | #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ |
22 | #define AAD_LEN 20 | 22 | #define AAD_LEN 20 |
@@ -35,10 +35,10 @@ static void gf_mulx(u8 *pad) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | 37 | ||
38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, | 38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, |
39 | size_t num_elem, | ||
40 | const u8 *addr[], const size_t *len, u8 *mac) | 39 | const u8 *addr[], const size_t *len, u8 *mac) |
41 | { | 40 | { |
41 | u8 scratch[2 * AES_BLOCK_SIZE]; | ||
42 | u8 *cbc, *pad; | 42 | u8 *cbc, *pad; |
43 | const u8 *pos, *end; | 43 | const u8 *pos, *end; |
44 | size_t i, e, left, total_len; | 44 | size_t i, e, left, total_len; |
@@ -95,7 +95,7 @@ static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, | |||
95 | } | 95 | } |
96 | 96 | ||
97 | 97 | ||
98 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | 98 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, |
99 | const u8 *data, size_t data_len, u8 *mic) | 99 | const u8 *data, size_t data_len, u8 *mic) |
100 | { | 100 | { |
101 | const u8 *addr[3]; | 101 | const u8 *addr[3]; |
@@ -110,7 +110,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | |||
110 | addr[2] = zero; | 110 | addr[2] = zero; |
111 | len[2] = CMAC_TLEN; | 111 | len[2] = CMAC_TLEN; |
112 | 112 | ||
113 | aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic); | 113 | aes_128_cmac_vector(tfm, 3, addr, len, mic); |
114 | } | 114 | } |
115 | 115 | ||
116 | 116 | ||
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 0eb9a4831508..20785a647254 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | 13 | ||
14 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); | 14 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); |
15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | 15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, |
16 | const u8 *data, size_t data_len, u8 *mic); | 16 | const u8 *data, size_t data_len, u8 *mic); |
17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); | 17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); |
18 | 18 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 295ab747663f..bfc36e904764 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -209,6 +209,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
209 | u8 seq[6] = {0}; | 209 | u8 seq[6] = {0}; |
210 | struct key_params params; | 210 | struct key_params params; |
211 | struct ieee80211_key *key = NULL; | 211 | struct ieee80211_key *key = NULL; |
212 | u64 pn64; | ||
212 | u32 iv32; | 213 | u32 iv32; |
213 | u16 iv16; | 214 | u16 iv16; |
214 | int err = -ENOENT; | 215 | int err = -ENOENT; |
@@ -256,22 +257,24 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
256 | params.seq_len = 6; | 257 | params.seq_len = 6; |
257 | break; | 258 | break; |
258 | case WLAN_CIPHER_SUITE_CCMP: | 259 | case WLAN_CIPHER_SUITE_CCMP: |
259 | seq[0] = key->u.ccmp.tx_pn[5]; | 260 | pn64 = atomic64_read(&key->u.ccmp.tx_pn); |
260 | seq[1] = key->u.ccmp.tx_pn[4]; | 261 | seq[0] = pn64; |
261 | seq[2] = key->u.ccmp.tx_pn[3]; | 262 | seq[1] = pn64 >> 8; |
262 | seq[3] = key->u.ccmp.tx_pn[2]; | 263 | seq[2] = pn64 >> 16; |
263 | seq[4] = key->u.ccmp.tx_pn[1]; | 264 | seq[3] = pn64 >> 24; |
264 | seq[5] = key->u.ccmp.tx_pn[0]; | 265 | seq[4] = pn64 >> 32; |
266 | seq[5] = pn64 >> 40; | ||
265 | params.seq = seq; | 267 | params.seq = seq; |
266 | params.seq_len = 6; | 268 | params.seq_len = 6; |
267 | break; | 269 | break; |
268 | case WLAN_CIPHER_SUITE_AES_CMAC: | 270 | case WLAN_CIPHER_SUITE_AES_CMAC: |
269 | seq[0] = key->u.aes_cmac.tx_pn[5]; | 271 | pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); |
270 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 272 | seq[0] = pn64; |
271 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 273 | seq[1] = pn64 >> 8; |
272 | seq[3] = key->u.aes_cmac.tx_pn[2]; | 274 | seq[2] = pn64 >> 16; |
273 | seq[4] = key->u.aes_cmac.tx_pn[1]; | 275 | seq[3] = pn64 >> 24; |
274 | seq[5] = key->u.aes_cmac.tx_pn[0]; | 276 | seq[4] = pn64 >> 32; |
277 | seq[5] = pn64 >> 40; | ||
275 | params.seq = seq; | 278 | params.seq = seq; |
276 | params.seq_len = 6; | 279 | params.seq_len = 6; |
277 | break; | 280 | break; |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 33c58b85c911..38e6101190d9 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -78,7 +78,7 @@ KEY_OPS(algorithm); | |||
78 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | 78 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, |
79 | size_t count, loff_t *ppos) | 79 | size_t count, loff_t *ppos) |
80 | { | 80 | { |
81 | const u8 *tpn; | 81 | u64 pn; |
82 | char buf[20]; | 82 | char buf[20]; |
83 | int len; | 83 | int len; |
84 | struct ieee80211_key *key = file->private_data; | 84 | struct ieee80211_key *key = file->private_data; |
@@ -94,15 +94,16 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
94 | key->u.tkip.tx.iv16); | 94 | key->u.tkip.tx.iv16); |
95 | break; | 95 | break; |
96 | case WLAN_CIPHER_SUITE_CCMP: | 96 | case WLAN_CIPHER_SUITE_CCMP: |
97 | tpn = key->u.ccmp.tx_pn; | 97 | pn = atomic64_read(&key->u.ccmp.tx_pn); |
98 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 98 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
99 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 99 | (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), |
100 | (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); | ||
100 | break; | 101 | break; |
101 | case WLAN_CIPHER_SUITE_AES_CMAC: | 102 | case WLAN_CIPHER_SUITE_AES_CMAC: |
102 | tpn = key->u.aes_cmac.tx_pn; | 103 | pn = atomic64_read(&key->u.aes_cmac.tx_pn); |
103 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 104 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
104 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | 105 | (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), |
105 | tpn[5]); | 106 | (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); |
106 | break; | 107 | break; |
107 | default: | 108 | default: |
108 | return 0; | 109 | return 0; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index edd2dd79c9be..b2d6bba44054 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -657,4 +657,12 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, | |||
657 | trace_drv_return_void(local); | 657 | trace_drv_return_void(local); |
658 | } | 658 | } |
659 | 659 | ||
660 | static inline void drv_rssi_callback(struct ieee80211_local *local, | ||
661 | const enum ieee80211_rssi_event event) | ||
662 | { | ||
663 | trace_drv_rssi_callback(local, event); | ||
664 | if (local->ops->rssi_callback) | ||
665 | local->ops->rssi_callback(&local->hw, event); | ||
666 | trace_drv_return_void(local); | ||
667 | } | ||
660 | #endif /* __MAC80211_DRIVER_OPS */ | 668 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 31a9dfa81f65..4470f6e8b845 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -1052,6 +1052,28 @@ TRACE_EVENT(drv_set_rekey_data, | |||
1052 | LOCAL_PR_ARG, VIF_PR_ARG) | 1052 | LOCAL_PR_ARG, VIF_PR_ARG) |
1053 | ); | 1053 | ); |
1054 | 1054 | ||
1055 | TRACE_EVENT(drv_rssi_callback, | ||
1056 | TP_PROTO(struct ieee80211_local *local, | ||
1057 | enum ieee80211_rssi_event rssi_event), | ||
1058 | |||
1059 | TP_ARGS(local, rssi_event), | ||
1060 | |||
1061 | TP_STRUCT__entry( | ||
1062 | LOCAL_ENTRY | ||
1063 | __field(u32, rssi_event) | ||
1064 | ), | ||
1065 | |||
1066 | TP_fast_assign( | ||
1067 | LOCAL_ASSIGN; | ||
1068 | __entry->rssi_event = rssi_event; | ||
1069 | ), | ||
1070 | |||
1071 | TP_printk( | ||
1072 | LOCAL_PR_FMT " rssi_event:%d", | ||
1073 | LOCAL_PR_ARG, __entry->rssi_event | ||
1074 | ) | ||
1075 | ); | ||
1076 | |||
1055 | /* | 1077 | /* |
1056 | * Tracing for API calls that drivers call. | 1078 | * Tracing for API calls that drivers call. |
1057 | */ | 1079 | */ |
@@ -1342,6 +1364,30 @@ TRACE_EVENT(api_gtk_rekey_notify, | |||
1342 | TP_printk(VIF_PR_FMT, VIF_PR_ARG) | 1364 | TP_printk(VIF_PR_FMT, VIF_PR_ARG) |
1343 | ); | 1365 | ); |
1344 | 1366 | ||
1367 | TRACE_EVENT(api_enable_rssi_reports, | ||
1368 | TP_PROTO(struct ieee80211_sub_if_data *sdata, | ||
1369 | int rssi_min_thold, int rssi_max_thold), | ||
1370 | |||
1371 | TP_ARGS(sdata, rssi_min_thold, rssi_max_thold), | ||
1372 | |||
1373 | TP_STRUCT__entry( | ||
1374 | VIF_ENTRY | ||
1375 | __field(int, rssi_min_thold) | ||
1376 | __field(int, rssi_max_thold) | ||
1377 | ), | ||
1378 | |||
1379 | TP_fast_assign( | ||
1380 | VIF_ASSIGN; | ||
1381 | __entry->rssi_min_thold = rssi_min_thold; | ||
1382 | __entry->rssi_max_thold = rssi_max_thold; | ||
1383 | ), | ||
1384 | |||
1385 | TP_printk( | ||
1386 | VIF_PR_FMT " rssi_min_thold =%d, rssi_max_thold = %d", | ||
1387 | VIF_PR_ARG, __entry->rssi_min_thold, __entry->rssi_max_thold | ||
1388 | ) | ||
1389 | ); | ||
1390 | |||
1345 | /* | 1391 | /* |
1346 | * Tracing for internal functions | 1392 | * Tracing for internal functions |
1347 | * (which may also be called in response to driver calls) | 1393 | * (which may also be called in response to driver calls) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4f2e424e8b1b..dda0d1ab34f3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -202,7 +202,22 @@ struct ieee80211_rx_data { | |||
202 | struct ieee80211_key *key; | 202 | struct ieee80211_key *key; |
203 | 203 | ||
204 | unsigned int flags; | 204 | unsigned int flags; |
205 | int queue; | 205 | |
206 | /* | ||
207 | * Index into sequence numbers array, 0..16 | ||
208 | * since the last (16) is used for non-QoS, | ||
209 | * will be 16 on non-QoS frames. | ||
210 | */ | ||
211 | int seqno_idx; | ||
212 | |||
213 | /* | ||
214 | * Index into the security IV/PN arrays, 0..16 | ||
215 | * since the last (16) is used for CCMP-encrypted | ||
216 | * management frames, will be set to 16 on mgmt | ||
217 | * frames and 0 on non-QoS frames. | ||
218 | */ | ||
219 | int security_idx; | ||
220 | |||
206 | u32 tkip_iv32; | 221 | u32 tkip_iv32; |
207 | u16 tkip_iv16; | 222 | u16 tkip_iv16; |
208 | }; | 223 | }; |
@@ -417,6 +432,14 @@ struct ieee80211_if_managed { | |||
417 | * generated for the current association. | 432 | * generated for the current association. |
418 | */ | 433 | */ |
419 | int last_cqm_event_signal; | 434 | int last_cqm_event_signal; |
435 | |||
436 | /* | ||
437 | * State variables for keeping track of RSSI of the AP currently | ||
438 | * connected to and informing driver when RSSI has gone | ||
439 | * below/above a certain threshold. | ||
440 | */ | ||
441 | int rssi_min_thold, rssi_max_thold; | ||
442 | int last_ave_beacon_signal; | ||
420 | }; | 443 | }; |
421 | 444 | ||
422 | struct ieee80211_if_ibss { | 445 | struct ieee80211_if_ibss { |
@@ -515,12 +538,14 @@ struct ieee80211_if_mesh { | |||
515 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | 538 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between |
516 | * associated stations and deliver multicast frames both | 539 | * associated stations and deliver multicast frames both |
517 | * back to wireless media and to the local net stack. | 540 | * back to wireless media and to the local net stack. |
541 | * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume. | ||
518 | */ | 542 | */ |
519 | enum ieee80211_sub_if_data_flags { | 543 | enum ieee80211_sub_if_data_flags { |
520 | IEEE80211_SDATA_ALLMULTI = BIT(0), | 544 | IEEE80211_SDATA_ALLMULTI = BIT(0), |
521 | IEEE80211_SDATA_PROMISC = BIT(1), | 545 | IEEE80211_SDATA_PROMISC = BIT(1), |
522 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), | 546 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), |
523 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), | 547 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), |
548 | IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), | ||
524 | }; | 549 | }; |
525 | 550 | ||
526 | /** | 551 | /** |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index dee30aea9ab3..cd5fb40d3fd4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -363,8 +363,7 @@ static int ieee80211_open(struct net_device *dev) | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | /* fail early if user set an invalid address */ | 365 | /* fail early if user set an invalid address */ |
366 | if (!is_zero_ether_addr(dev->dev_addr) && | 366 | if (!is_valid_ether_addr(dev->dev_addr)) |
367 | !is_valid_ether_addr(dev->dev_addr)) | ||
368 | return -EADDRNOTAVAIL; | 367 | return -EADDRNOTAVAIL; |
369 | 368 | ||
370 | err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); | 369 | err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); |
@@ -1130,8 +1129,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1130 | 1129 | ||
1131 | ASSERT_RTNL(); | 1130 | ASSERT_RTNL(); |
1132 | 1131 | ||
1133 | ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size, | 1132 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, |
1134 | name, ieee80211_if_setup, local->hw.queues); | 1133 | name, ieee80211_if_setup, local->hw.queues, 1); |
1135 | if (!ndev) | 1134 | if (!ndev) |
1136 | return -ENOMEM; | 1135 | return -ENOMEM; |
1137 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1136 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 1208a7878bfd..739bee13e813 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -369,6 +369,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
369 | get_unaligned_le16(seq); | 369 | get_unaligned_le16(seq); |
370 | } | 370 | } |
371 | } | 371 | } |
372 | spin_lock_init(&key->u.tkip.txlock); | ||
372 | break; | 373 | break; |
373 | case WLAN_CIPHER_SUITE_CCMP: | 374 | case WLAN_CIPHER_SUITE_CCMP: |
374 | key->conf.iv_len = CCMP_HDR_LEN; | 375 | key->conf.iv_len = CCMP_HDR_LEN; |
@@ -625,3 +626,77 @@ void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, | |||
625 | cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp); | 626 | cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp); |
626 | } | 627 | } |
627 | EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); | 628 | EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); |
629 | |||
630 | void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf, | ||
631 | struct ieee80211_key_seq *seq) | ||
632 | { | ||
633 | struct ieee80211_key *key; | ||
634 | u64 pn64; | ||
635 | |||
636 | if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV))) | ||
637 | return; | ||
638 | |||
639 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
640 | |||
641 | switch (key->conf.cipher) { | ||
642 | case WLAN_CIPHER_SUITE_TKIP: | ||
643 | seq->tkip.iv32 = key->u.tkip.tx.iv32; | ||
644 | seq->tkip.iv16 = key->u.tkip.tx.iv16; | ||
645 | break; | ||
646 | case WLAN_CIPHER_SUITE_CCMP: | ||
647 | pn64 = atomic64_read(&key->u.ccmp.tx_pn); | ||
648 | seq->ccmp.pn[5] = pn64; | ||
649 | seq->ccmp.pn[4] = pn64 >> 8; | ||
650 | seq->ccmp.pn[3] = pn64 >> 16; | ||
651 | seq->ccmp.pn[2] = pn64 >> 24; | ||
652 | seq->ccmp.pn[1] = pn64 >> 32; | ||
653 | seq->ccmp.pn[0] = pn64 >> 40; | ||
654 | break; | ||
655 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
656 | pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); | ||
657 | seq->ccmp.pn[5] = pn64; | ||
658 | seq->ccmp.pn[4] = pn64 >> 8; | ||
659 | seq->ccmp.pn[3] = pn64 >> 16; | ||
660 | seq->ccmp.pn[2] = pn64 >> 24; | ||
661 | seq->ccmp.pn[1] = pn64 >> 32; | ||
662 | seq->ccmp.pn[0] = pn64 >> 40; | ||
663 | break; | ||
664 | default: | ||
665 | WARN_ON(1); | ||
666 | } | ||
667 | } | ||
668 | EXPORT_SYMBOL(ieee80211_get_key_tx_seq); | ||
669 | |||
670 | void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, | ||
671 | int tid, struct ieee80211_key_seq *seq) | ||
672 | { | ||
673 | struct ieee80211_key *key; | ||
674 | const u8 *pn; | ||
675 | |||
676 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
677 | |||
678 | switch (key->conf.cipher) { | ||
679 | case WLAN_CIPHER_SUITE_TKIP: | ||
680 | if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES)) | ||
681 | return; | ||
682 | seq->tkip.iv32 = key->u.tkip.rx[tid].iv32; | ||
683 | seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; | ||
684 | break; | ||
685 | case WLAN_CIPHER_SUITE_CCMP: | ||
686 | if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES)) | ||
687 | return; | ||
688 | if (tid < 0) | ||
689 | pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES]; | ||
690 | else | ||
691 | pn = key->u.ccmp.rx_pn[tid]; | ||
692 | memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); | ||
693 | break; | ||
694 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
695 | if (WARN_ON(tid != 0)) | ||
696 | return; | ||
697 | pn = key->u.aes_cmac.rx_pn; | ||
698 | memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN); | ||
699 | break; | ||
700 | } | ||
701 | } | ||
702 | EXPORT_SYMBOL(ieee80211_get_key_rx_seq); | ||
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index d801d5351336..7d4e31f037d7 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -28,8 +28,9 @@ | |||
28 | #define CCMP_PN_LEN 6 | 28 | #define CCMP_PN_LEN 6 |
29 | #define TKIP_IV_LEN 8 | 29 | #define TKIP_IV_LEN 8 |
30 | #define TKIP_ICV_LEN 4 | 30 | #define TKIP_ICV_LEN 4 |
31 | #define CMAC_PN_LEN 6 | ||
31 | 32 | ||
32 | #define NUM_RX_DATA_QUEUES 17 | 33 | #define NUM_RX_DATA_QUEUES 16 |
33 | 34 | ||
34 | struct ieee80211_local; | 35 | struct ieee80211_local; |
35 | struct ieee80211_sub_if_data; | 36 | struct ieee80211_sub_if_data; |
@@ -40,9 +41,11 @@ struct sta_info; | |||
40 | * | 41 | * |
41 | * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present | 42 | * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present |
42 | * in the hardware for TX crypto hardware acceleration. | 43 | * in the hardware for TX crypto hardware acceleration. |
44 | * @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped. | ||
43 | */ | 45 | */ |
44 | enum ieee80211_internal_key_flags { | 46 | enum ieee80211_internal_key_flags { |
45 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), | 47 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), |
48 | KEY_FLAG_TAINTED = BIT(1), | ||
46 | }; | 49 | }; |
47 | 50 | ||
48 | enum ieee80211_internal_tkip_state { | 51 | enum ieee80211_internal_tkip_state { |
@@ -52,9 +55,10 @@ enum ieee80211_internal_tkip_state { | |||
52 | }; | 55 | }; |
53 | 56 | ||
54 | struct tkip_ctx { | 57 | struct tkip_ctx { |
55 | u32 iv32; | 58 | u32 iv32; /* current iv32 */ |
56 | u16 iv16; | 59 | u16 iv16; /* current iv16 */ |
57 | u16 p1k[5]; | 60 | u16 p1k[5]; /* p1k cache */ |
61 | u32 p1k_iv32; /* iv32 for which p1k computed */ | ||
58 | enum ieee80211_internal_tkip_state state; | 62 | enum ieee80211_internal_tkip_state state; |
59 | }; | 63 | }; |
60 | 64 | ||
@@ -71,6 +75,9 @@ struct ieee80211_key { | |||
71 | 75 | ||
72 | union { | 76 | union { |
73 | struct { | 77 | struct { |
78 | /* protects tx context */ | ||
79 | spinlock_t txlock; | ||
80 | |||
74 | /* last used TSC */ | 81 | /* last used TSC */ |
75 | struct tkip_ctx tx; | 82 | struct tkip_ctx tx; |
76 | 83 | ||
@@ -78,32 +85,23 @@ struct ieee80211_key { | |||
78 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; | 85 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; |
79 | } tkip; | 86 | } tkip; |
80 | struct { | 87 | struct { |
81 | u8 tx_pn[6]; | 88 | atomic64_t tx_pn; |
82 | /* | 89 | /* |
83 | * Last received packet number. The first | 90 | * Last received packet number. The first |
84 | * NUM_RX_DATA_QUEUES counters are used with Data | 91 | * NUM_RX_DATA_QUEUES counters are used with Data |
85 | * frames and the last counter is used with Robust | 92 | * frames and the last counter is used with Robust |
86 | * Management frames. | 93 | * Management frames. |
87 | */ | 94 | */ |
88 | u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6]; | 95 | u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN]; |
89 | struct crypto_cipher *tfm; | 96 | struct crypto_cipher *tfm; |
90 | u32 replays; /* dot11RSNAStatsCCMPReplays */ | 97 | u32 replays; /* dot11RSNAStatsCCMPReplays */ |
91 | /* scratch buffers for virt_to_page() (crypto API) */ | ||
92 | #ifndef AES_BLOCK_LEN | ||
93 | #define AES_BLOCK_LEN 16 | ||
94 | #endif | ||
95 | u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; | ||
96 | u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; | ||
97 | } ccmp; | 98 | } ccmp; |
98 | struct { | 99 | struct { |
99 | u8 tx_pn[6]; | 100 | atomic64_t tx_pn; |
100 | u8 rx_pn[6]; | 101 | u8 rx_pn[CMAC_PN_LEN]; |
101 | struct crypto_cipher *tfm; | 102 | struct crypto_cipher *tfm; |
102 | u32 replays; /* dot11RSNAStatsCMACReplays */ | 103 | u32 replays; /* dot11RSNAStatsCMACReplays */ |
103 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ | 104 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ |
104 | /* scratch buffers for virt_to_page() (crypto API) */ | ||
105 | u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; | ||
106 | u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; | ||
107 | } aes_cmac; | 105 | } aes_cmac; |
108 | } u; | 106 | } u; |
109 | 107 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 182cda66ebef..c99237cd4b98 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1763,6 +1763,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1763 | ifmgd->ave_beacon_signal = rx_status->signal * 16; | 1763 | ifmgd->ave_beacon_signal = rx_status->signal * 16; |
1764 | ifmgd->last_cqm_event_signal = 0; | 1764 | ifmgd->last_cqm_event_signal = 0; |
1765 | ifmgd->count_beacon_signal = 1; | 1765 | ifmgd->count_beacon_signal = 1; |
1766 | ifmgd->last_ave_beacon_signal = 0; | ||
1766 | } else { | 1767 | } else { |
1767 | ifmgd->ave_beacon_signal = | 1768 | ifmgd->ave_beacon_signal = |
1768 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | 1769 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + |
@@ -1770,6 +1771,28 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1770 | ifmgd->ave_beacon_signal) / 16; | 1771 | ifmgd->ave_beacon_signal) / 16; |
1771 | ifmgd->count_beacon_signal++; | 1772 | ifmgd->count_beacon_signal++; |
1772 | } | 1773 | } |
1774 | |||
1775 | if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold && | ||
1776 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { | ||
1777 | int sig = ifmgd->ave_beacon_signal; | ||
1778 | int last_sig = ifmgd->last_ave_beacon_signal; | ||
1779 | |||
1780 | /* | ||
1781 | * if signal crosses either of the boundaries, invoke callback | ||
1782 | * with appropriate parameters | ||
1783 | */ | ||
1784 | if (sig > ifmgd->rssi_max_thold && | ||
1785 | (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) { | ||
1786 | ifmgd->last_ave_beacon_signal = sig; | ||
1787 | drv_rssi_callback(local, RSSI_EVENT_HIGH); | ||
1788 | } else if (sig < ifmgd->rssi_min_thold && | ||
1789 | (last_sig >= ifmgd->rssi_max_thold || | ||
1790 | last_sig == 0)) { | ||
1791 | ifmgd->last_ave_beacon_signal = sig; | ||
1792 | drv_rssi_callback(local, RSSI_EVENT_LOW); | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1773 | if (bss_conf->cqm_rssi_thold && | 1796 | if (bss_conf->cqm_rssi_thold && |
1774 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && | 1797 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && |
1775 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | 1798 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { |
@@ -2029,7 +2052,7 @@ static void ieee80211_sta_timer(unsigned long data) | |||
2029 | } | 2052 | } |
2030 | 2053 | ||
2031 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | 2054 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, |
2032 | u8 *bssid) | 2055 | u8 *bssid, u8 reason) |
2033 | { | 2056 | { |
2034 | struct ieee80211_local *local = sdata->local; | 2057 | struct ieee80211_local *local = sdata->local; |
2035 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2058 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -2047,8 +2070,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2047 | * but that's not a problem. | 2070 | * but that's not a problem. |
2048 | */ | 2071 | */ |
2049 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2072 | ieee80211_send_deauth_disassoc(sdata, bssid, |
2050 | IEEE80211_STYPE_DEAUTH, | 2073 | IEEE80211_STYPE_DEAUTH, reason, |
2051 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
2052 | NULL, true); | 2074 | NULL, true); |
2053 | mutex_lock(&ifmgd->mtx); | 2075 | mutex_lock(&ifmgd->mtx); |
2054 | } | 2076 | } |
@@ -2094,7 +2116,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2094 | " AP %pM, disconnecting.\n", | 2116 | " AP %pM, disconnecting.\n", |
2095 | sdata->name, bssid); | 2117 | sdata->name, bssid); |
2096 | #endif | 2118 | #endif |
2097 | ieee80211_sta_connection_lost(sdata, bssid); | 2119 | ieee80211_sta_connection_lost(sdata, bssid, |
2120 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | ||
2098 | } | 2121 | } |
2099 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) | 2122 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) |
2100 | run_again(ifmgd, ifmgd->probe_timeout); | 2123 | run_again(ifmgd, ifmgd->probe_timeout); |
@@ -2106,7 +2129,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2106 | sdata->name, | 2129 | sdata->name, |
2107 | bssid, probe_wait_ms); | 2130 | bssid, probe_wait_ms); |
2108 | #endif | 2131 | #endif |
2109 | ieee80211_sta_connection_lost(sdata, bssid); | 2132 | ieee80211_sta_connection_lost(sdata, bssid, |
2133 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | ||
2110 | } else if (ifmgd->probe_send_count < max_tries) { | 2134 | } else if (ifmgd->probe_send_count < max_tries) { |
2111 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2135 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
2112 | wiphy_debug(local->hw.wiphy, | 2136 | wiphy_debug(local->hw.wiphy, |
@@ -2128,7 +2152,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2128 | sdata->name, | 2152 | sdata->name, |
2129 | bssid, probe_wait_ms); | 2153 | bssid, probe_wait_ms); |
2130 | 2154 | ||
2131 | ieee80211_sta_connection_lost(sdata, bssid); | 2155 | ieee80211_sta_connection_lost(sdata, bssid, |
2156 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | ||
2132 | } | 2157 | } |
2133 | } | 2158 | } |
2134 | 2159 | ||
@@ -2215,6 +2240,27 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | |||
2215 | { | 2240 | { |
2216 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2241 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2217 | 2242 | ||
2243 | if (!ifmgd->associated) | ||
2244 | return; | ||
2245 | |||
2246 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
2247 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
2248 | mutex_lock(&ifmgd->mtx); | ||
2249 | if (ifmgd->associated) { | ||
2250 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
2251 | wiphy_debug(sdata->local->hw.wiphy, | ||
2252 | "%s: driver requested disconnect after resume.\n", | ||
2253 | sdata->name); | ||
2254 | #endif | ||
2255 | ieee80211_sta_connection_lost(sdata, | ||
2256 | ifmgd->associated->bssid, | ||
2257 | WLAN_REASON_UNSPECIFIED); | ||
2258 | mutex_unlock(&ifmgd->mtx); | ||
2259 | return; | ||
2260 | } | ||
2261 | mutex_unlock(&ifmgd->mtx); | ||
2262 | } | ||
2263 | |||
2218 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) | 2264 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) |
2219 | add_timer(&ifmgd->timer); | 2265 | add_timer(&ifmgd->timer); |
2220 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | 2266 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5493ecd1e93..fe2c2a717793 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -331,7 +331,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
331 | { | 331 | { |
332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
333 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 333 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
334 | int tid; | 334 | int tid, seqno_idx, security_idx; |
335 | 335 | ||
336 | /* does the frame have a qos control field? */ | 336 | /* does the frame have a qos control field? */ |
337 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 337 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
@@ -340,6 +340,9 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
340 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 340 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
341 | if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) | 341 | if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) |
342 | status->rx_flags |= IEEE80211_RX_AMSDU; | 342 | status->rx_flags |= IEEE80211_RX_AMSDU; |
343 | |||
344 | seqno_idx = tid; | ||
345 | security_idx = tid; | ||
343 | } else { | 346 | } else { |
344 | /* | 347 | /* |
345 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): | 348 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): |
@@ -352,10 +355,15 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
352 | * | 355 | * |
353 | * We also use that counter for non-QoS STAs. | 356 | * We also use that counter for non-QoS STAs. |
354 | */ | 357 | */ |
355 | tid = NUM_RX_DATA_QUEUES - 1; | 358 | seqno_idx = NUM_RX_DATA_QUEUES; |
359 | security_idx = 0; | ||
360 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
361 | security_idx = NUM_RX_DATA_QUEUES; | ||
362 | tid = 0; | ||
356 | } | 363 | } |
357 | 364 | ||
358 | rx->queue = tid; | 365 | rx->seqno_idx = seqno_idx; |
366 | rx->security_idx = security_idx; | ||
359 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. | 367 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. |
360 | * For now, set skb->priority to 0 for other cases. */ | 368 | * For now, set skb->priority to 0 for other cases. */ |
361 | rx->skb->priority = (tid > 7) ? 0 : tid; | 369 | rx->skb->priority = (tid > 7) ? 0 : tid; |
@@ -810,7 +818,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
810 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ | 818 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ |
811 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { | 819 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { |
812 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | 820 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
813 | rx->sta->last_seq_ctrl[rx->queue] == | 821 | rx->sta->last_seq_ctrl[rx->seqno_idx] == |
814 | hdr->seq_ctrl)) { | 822 | hdr->seq_ctrl)) { |
815 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { | 823 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { |
816 | rx->local->dot11FrameDuplicateCount++; | 824 | rx->local->dot11FrameDuplicateCount++; |
@@ -818,7 +826,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
818 | } | 826 | } |
819 | return RX_DROP_UNUSABLE; | 827 | return RX_DROP_UNUSABLE; |
820 | } else | 828 | } else |
821 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; | 829 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; |
822 | } | 830 | } |
823 | 831 | ||
824 | if (unlikely(rx->skb->len < 16)) { | 832 | if (unlikely(rx->skb->len < 16)) { |
@@ -1011,6 +1019,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1011 | } | 1019 | } |
1012 | 1020 | ||
1013 | if (rx->key) { | 1021 | if (rx->key) { |
1022 | if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) | ||
1023 | return RX_DROP_MONITOR; | ||
1024 | |||
1014 | rx->key->tx_rx_count++; | 1025 | rx->key->tx_rx_count++; |
1015 | /* TODO: add threshold stuff again */ | 1026 | /* TODO: add threshold stuff again */ |
1016 | } else { | 1027 | } else { |
@@ -1374,11 +1385,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1374 | if (frag == 0) { | 1385 | if (frag == 0) { |
1375 | /* This is the first fragment of a new frame. */ | 1386 | /* This is the first fragment of a new frame. */ |
1376 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1387 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1377 | rx->queue, &(rx->skb)); | 1388 | rx->seqno_idx, &(rx->skb)); |
1378 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && | 1389 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && |
1379 | ieee80211_has_protected(fc)) { | 1390 | ieee80211_has_protected(fc)) { |
1380 | int queue = ieee80211_is_mgmt(fc) ? | 1391 | int queue = rx->security_idx; |
1381 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1382 | /* Store CCMP PN so that we can verify that the next | 1392 | /* Store CCMP PN so that we can verify that the next |
1383 | * fragment has a sequential PN value. */ | 1393 | * fragment has a sequential PN value. */ |
1384 | entry->ccmp = 1; | 1394 | entry->ccmp = 1; |
@@ -1392,7 +1402,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1392 | /* This is a fragment for a frame that should already be pending in | 1402 | /* This is a fragment for a frame that should already be pending in |
1393 | * fragment cache. Add this fragment to the end of the pending entry. | 1403 | * fragment cache. Add this fragment to the end of the pending entry. |
1394 | */ | 1404 | */ |
1395 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); | 1405 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, |
1406 | rx->seqno_idx, hdr); | ||
1396 | if (!entry) { | 1407 | if (!entry) { |
1397 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 1408 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
1398 | return RX_DROP_MONITOR; | 1409 | return RX_DROP_MONITOR; |
@@ -1412,8 +1423,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1412 | if (pn[i]) | 1423 | if (pn[i]) |
1413 | break; | 1424 | break; |
1414 | } | 1425 | } |
1415 | queue = ieee80211_is_mgmt(fc) ? | 1426 | queue = rx->security_idx; |
1416 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1417 | rpn = rx->key->u.ccmp.rx_pn[queue]; | 1427 | rpn = rx->key->u.ccmp.rx_pn[queue]; |
1418 | if (memcmp(pn, rpn, CCMP_PN_LEN)) | 1428 | if (memcmp(pn, rpn, CCMP_PN_LEN)) |
1419 | return RX_DROP_UNUSABLE; | 1429 | return RX_DROP_UNUSABLE; |
@@ -2590,7 +2600,9 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2590 | .sta = sta, | 2600 | .sta = sta, |
2591 | .sdata = sta->sdata, | 2601 | .sdata = sta->sdata, |
2592 | .local = sta->local, | 2602 | .local = sta->local, |
2593 | .queue = tid, | 2603 | /* This is OK -- must be QoS data frame */ |
2604 | .security_idx = tid, | ||
2605 | .seqno_idx = tid, | ||
2594 | .flags = 0, | 2606 | .flags = 0, |
2595 | }; | 2607 | }; |
2596 | struct tid_ampdu_rx *tid_agg_rx; | 2608 | struct tid_ampdu_rx *tid_agg_rx; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index a06d64ebc177..28beb78e601e 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -287,7 +287,8 @@ struct sta_info { | |||
287 | unsigned long rx_dropped; | 287 | unsigned long rx_dropped; |
288 | int last_signal; | 288 | int last_signal; |
289 | struct ewma avg_signal; | 289 | struct ewma avg_signal; |
290 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 290 | /* Plus 1 for non-QoS frames */ |
291 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1]; | ||
291 | 292 | ||
292 | /* Updated from TX status path only, no locking requirements */ | 293 | /* Updated from TX status path only, no locking requirements */ |
293 | unsigned long tx_filtered_count; | 294 | unsigned long tx_filtered_count; |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 757e4eb2baf7..cc79e697cdb2 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -101,6 +101,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx, | |||
101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; | 101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; |
102 | } | 102 | } |
103 | ctx->state = TKIP_STATE_PHASE1_DONE; | 103 | ctx->state = TKIP_STATE_PHASE1_DONE; |
104 | ctx->p1k_iv32 = tsc_IV32; | ||
104 | } | 105 | } |
105 | 106 | ||
106 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, | 107 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, |
@@ -140,60 +141,69 @@ static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, | |||
140 | /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets | 141 | /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets |
141 | * of the IV. Returns pointer to the octet following IVs (i.e., beginning of | 142 | * of the IV. Returns pointer to the octet following IVs (i.e., beginning of |
142 | * the packet payload). */ | 143 | * the packet payload). */ |
143 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16) | 144 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key) |
144 | { | 145 | { |
145 | pos = write_tkip_iv(pos, iv16); | 146 | lockdep_assert_held(&key->u.tkip.txlock); |
147 | |||
148 | pos = write_tkip_iv(pos, key->u.tkip.tx.iv16); | ||
146 | *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; | 149 | *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; |
147 | put_unaligned_le32(key->u.tkip.tx.iv32, pos); | 150 | put_unaligned_le32(key->u.tkip.tx.iv32, pos); |
148 | return pos + 4; | 151 | return pos + 4; |
149 | } | 152 | } |
150 | 153 | ||
151 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | 154 | static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32) |
152 | struct sk_buff *skb, enum ieee80211_tkip_key_type type, | ||
153 | u8 *outkey) | ||
154 | { | 155 | { |
155 | struct ieee80211_key *key = (struct ieee80211_key *) | 156 | struct ieee80211_sub_if_data *sdata = key->sdata; |
156 | container_of(keyconf, struct ieee80211_key, conf); | 157 | struct tkip_ctx *ctx = &key->u.tkip.tx; |
157 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 158 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
158 | u8 *data; | ||
159 | const u8 *tk; | ||
160 | struct tkip_ctx *ctx; | ||
161 | u16 iv16; | ||
162 | u32 iv32; | ||
163 | |||
164 | data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control); | ||
165 | iv16 = data[2] | (data[0] << 8); | ||
166 | iv32 = get_unaligned_le32(&data[4]); | ||
167 | |||
168 | tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | ||
169 | ctx = &key->u.tkip.tx; | ||
170 | 159 | ||
171 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 160 | lockdep_assert_held(&key->u.tkip.txlock); |
172 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", | 161 | |
173 | iv16, iv32); | 162 | /* |
174 | 163 | * Update the P1K when the IV32 is different from the value it | |
175 | if (iv32 != ctx->iv32) { | 164 | * had when we last computed it (or when not initialised yet). |
176 | printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n", | 165 | * This might flip-flop back and forth if packets are processed |
177 | iv32, ctx->iv32); | 166 | * out-of-order due to the different ACs, but then we have to |
178 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " | 167 | * just compute the P1K more often. |
179 | "fragmented packet\n"); | 168 | */ |
180 | } | 169 | if (ctx->p1k_iv32 != iv32 || ctx->state == TKIP_STATE_NOT_INIT) |
181 | #endif | 170 | tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32); |
171 | } | ||
182 | 172 | ||
183 | /* Update the p1k only when the iv16 in the packet wraps around, this | 173 | void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf, |
184 | * might occur after the wrap around of iv16 in the key in case of | 174 | u32 iv32, u16 *p1k) |
185 | * fragmented packets. */ | 175 | { |
186 | if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) | 176 | struct ieee80211_key *key = (struct ieee80211_key *) |
187 | tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); | 177 | container_of(keyconf, struct ieee80211_key, conf); |
178 | struct tkip_ctx *ctx = &key->u.tkip.tx; | ||
179 | unsigned long flags; | ||
188 | 180 | ||
189 | if (type == IEEE80211_TKIP_P1_KEY) { | 181 | spin_lock_irqsave(&key->u.tkip.txlock, flags); |
190 | memcpy(outkey, ctx->p1k, sizeof(u16) * 5); | 182 | ieee80211_compute_tkip_p1k(key, iv32); |
191 | return; | 183 | memcpy(p1k, ctx->p1k, sizeof(ctx->p1k)); |
192 | } | 184 | spin_unlock_irqrestore(&key->u.tkip.txlock, flags); |
185 | } | ||
186 | EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv); | ||
193 | 187 | ||
194 | tkip_mixing_phase2(tk, ctx, iv16, outkey); | 188 | void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, |
189 | struct sk_buff *skb, u8 *p2k) | ||
190 | { | ||
191 | struct ieee80211_key *key = (struct ieee80211_key *) | ||
192 | container_of(keyconf, struct ieee80211_key, conf); | ||
193 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | ||
194 | struct tkip_ctx *ctx = &key->u.tkip.tx; | ||
195 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
196 | const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control); | ||
197 | u32 iv32 = get_unaligned_le32(&data[4]); | ||
198 | u16 iv16 = data[2] | (data[0] << 8); | ||
199 | unsigned long flags; | ||
200 | |||
201 | spin_lock_irqsave(&key->u.tkip.txlock, flags); | ||
202 | ieee80211_compute_tkip_p1k(key, iv32); | ||
203 | tkip_mixing_phase2(tk, ctx, iv16, p2k); | ||
204 | spin_unlock_irqrestore(&key->u.tkip.txlock, flags); | ||
195 | } | 205 | } |
196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | 206 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); |
197 | 207 | ||
198 | /* | 208 | /* |
199 | * Encrypt packet payload with TKIP using @key. @pos is a pointer to the | 209 | * Encrypt packet payload with TKIP using @key. @pos is a pointer to the |
@@ -204,19 +214,15 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key); | |||
204 | */ | 214 | */ |
205 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, | 215 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, |
206 | struct ieee80211_key *key, | 216 | struct ieee80211_key *key, |
207 | u8 *pos, size_t payload_len, u8 *ta) | 217 | struct sk_buff *skb, |
218 | u8 *payload, size_t payload_len) | ||
208 | { | 219 | { |
209 | u8 rc4key[16]; | 220 | u8 rc4key[16]; |
210 | struct tkip_ctx *ctx = &key->u.tkip.tx; | ||
211 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | ||
212 | |||
213 | /* Calculate per-packet key */ | ||
214 | if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) | ||
215 | tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); | ||
216 | 221 | ||
217 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); | 222 | ieee80211_get_tkip_p2k(&key->conf, skb, rc4key); |
218 | 223 | ||
219 | return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); | 224 | return ieee80211_wep_encrypt_data(tfm, rc4key, 16, |
225 | payload, payload_len); | ||
220 | } | 226 | } |
221 | 227 | ||
222 | /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the | 228 | /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the |
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index 1cab9c86978f..e3ecb659b90a 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h | |||
@@ -13,11 +13,13 @@ | |||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | #include "key.h" | 14 | #include "key.h" |
15 | 15 | ||
16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); | 16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key); |
17 | 17 | ||
18 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, | 18 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, |
19 | struct ieee80211_key *key, | 19 | struct ieee80211_key *key, |
20 | u8 *pos, size_t payload_len, u8 *ta); | 20 | struct sk_buff *skb, |
21 | u8 *payload, size_t payload_len); | ||
22 | |||
21 | enum { | 23 | enum { |
22 | TKIP_DECRYPT_OK = 0, | 24 | TKIP_DECRYPT_OK = 0, |
23 | TKIP_DECRYPT_NO_EXT_IV = -1, | 25 | TKIP_DECRYPT_NO_EXT_IV = -1, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e8d0d2d22665..8cb0d2d0ac69 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -589,6 +589,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
589 | break; | 589 | break; |
590 | } | 590 | } |
591 | 591 | ||
592 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED)) | ||
593 | return TX_DROP; | ||
594 | |||
592 | if (!skip_hw && tx->key && | 595 | if (!skip_hw && tx->key && |
593 | tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 596 | tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
594 | info->control.hw_key = &tx->key->conf; | 597 | info->control.hw_key = &tx->key->conf; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 652e5695225a..5bfb80cba634 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1334,6 +1334,33 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1334 | return 0; | 1334 | return 0; |
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | void ieee80211_resume_disconnect(struct ieee80211_vif *vif) | ||
1338 | { | ||
1339 | struct ieee80211_sub_if_data *sdata; | ||
1340 | struct ieee80211_local *local; | ||
1341 | struct ieee80211_key *key; | ||
1342 | |||
1343 | if (WARN_ON(!vif)) | ||
1344 | return; | ||
1345 | |||
1346 | sdata = vif_to_sdata(vif); | ||
1347 | local = sdata->local; | ||
1348 | |||
1349 | if (WARN_ON(!local->resuming)) | ||
1350 | return; | ||
1351 | |||
1352 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
1353 | return; | ||
1354 | |||
1355 | sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME; | ||
1356 | |||
1357 | mutex_lock(&local->key_mtx); | ||
1358 | list_for_each_entry(key, &sdata->key_list, list) | ||
1359 | key->flags |= KEY_FLAG_TAINTED; | ||
1360 | mutex_unlock(&local->key_mtx); | ||
1361 | } | ||
1362 | EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect); | ||
1363 | |||
1337 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | 1364 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, |
1338 | enum ieee80211_smps_mode *smps_mode) | 1365 | enum ieee80211_smps_mode *smps_mode) |
1339 | { | 1366 | { |
@@ -1450,3 +1477,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) | |||
1450 | 1477 | ||
1451 | return pos; | 1478 | return pos; |
1452 | } | 1479 | } |
1480 | |||
1481 | static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, | ||
1482 | int rssi_min_thold, | ||
1483 | int rssi_max_thold) | ||
1484 | { | ||
1485 | trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); | ||
1486 | |||
1487 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | ||
1488 | return; | ||
1489 | |||
1490 | /* | ||
1491 | * Scale up threshold values before storing it, as the RSSI averaging | ||
1492 | * algorithm uses a scaled up value as well. Change this scaling | ||
1493 | * factor if the RSSI averaging algorithm changes. | ||
1494 | */ | ||
1495 | sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; | ||
1496 | sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; | ||
1497 | } | ||
1498 | |||
1499 | void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, | ||
1500 | int rssi_min_thold, | ||
1501 | int rssi_max_thold) | ||
1502 | { | ||
1503 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1504 | |||
1505 | WARN_ON(rssi_min_thold == rssi_max_thold || | ||
1506 | rssi_min_thold > rssi_max_thold); | ||
1507 | |||
1508 | _ieee80211_enable_rssi_reports(sdata, rssi_min_thold, | ||
1509 | rssi_max_thold); | ||
1510 | } | ||
1511 | EXPORT_SYMBOL(ieee80211_enable_rssi_reports); | ||
1512 | |||
1513 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) | ||
1514 | { | ||
1515 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1516 | |||
1517 | _ieee80211_enable_rssi_reports(sdata, 0, 0); | ||
1518 | } | ||
1519 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8f6a302d2ac3..7bc8702808fa 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/gfp.h> | 15 | #include <linux/gfp.h> |
16 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include <crypto/aes.h> | ||
18 | 19 | ||
19 | #include "ieee80211_i.h" | 20 | #include "ieee80211_i.h" |
20 | #include "michael.h" | 21 | #include "michael.h" |
@@ -86,11 +87,6 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
86 | struct sk_buff *skb = rx->skb; | 87 | struct sk_buff *skb = rx->skb; |
87 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 88 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
88 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 89 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
89 | int queue = rx->queue; | ||
90 | |||
91 | /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ | ||
92 | if (rx->queue == NUM_RX_DATA_QUEUES - 1) | ||
93 | queue = 0; | ||
94 | 90 | ||
95 | /* | 91 | /* |
96 | * it makes no sense to check for MIC errors on anything other | 92 | * it makes no sense to check for MIC errors on anything other |
@@ -153,8 +149,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
153 | 149 | ||
154 | update_iv: | 150 | update_iv: |
155 | /* update IV in key information to be able to detect replays */ | 151 | /* update IV in key information to be able to detect replays */ |
156 | rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32; | 152 | rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; |
157 | rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16; | 153 | rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; |
158 | 154 | ||
159 | return RX_CONTINUE; | 155 | return RX_CONTINUE; |
160 | 156 | ||
@@ -176,6 +172,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
176 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 172 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
177 | struct ieee80211_key *key = tx->key; | 173 | struct ieee80211_key *key = tx->key; |
178 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 174 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
175 | unsigned long flags; | ||
179 | unsigned int hdrlen; | 176 | unsigned int hdrlen; |
180 | int len, tail; | 177 | int len, tail; |
181 | u8 *pos; | 178 | u8 *pos; |
@@ -203,11 +200,12 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
203 | pos += hdrlen; | 200 | pos += hdrlen; |
204 | 201 | ||
205 | /* Increase IV for the frame */ | 202 | /* Increase IV for the frame */ |
203 | spin_lock_irqsave(&key->u.tkip.txlock, flags); | ||
206 | key->u.tkip.tx.iv16++; | 204 | key->u.tkip.tx.iv16++; |
207 | if (key->u.tkip.tx.iv16 == 0) | 205 | if (key->u.tkip.tx.iv16 == 0) |
208 | key->u.tkip.tx.iv32++; | 206 | key->u.tkip.tx.iv32++; |
209 | 207 | pos = ieee80211_tkip_add_iv(pos, key); | |
210 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | 208 | spin_unlock_irqrestore(&key->u.tkip.txlock, flags); |
211 | 209 | ||
212 | /* hwaccel - with software IV */ | 210 | /* hwaccel - with software IV */ |
213 | if (info->control.hw_key) | 211 | if (info->control.hw_key) |
@@ -216,9 +214,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
216 | /* Add room for ICV */ | 214 | /* Add room for ICV */ |
217 | skb_put(skb, TKIP_ICV_LEN); | 215 | skb_put(skb, TKIP_ICV_LEN); |
218 | 216 | ||
219 | hdr = (struct ieee80211_hdr *) skb->data; | ||
220 | return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, | 217 | return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, |
221 | key, pos, len, hdr->addr2); | 218 | key, skb, pos, len); |
222 | } | 219 | } |
223 | 220 | ||
224 | 221 | ||
@@ -246,11 +243,6 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
246 | struct ieee80211_key *key = rx->key; | 243 | struct ieee80211_key *key = rx->key; |
247 | struct sk_buff *skb = rx->skb; | 244 | struct sk_buff *skb = rx->skb; |
248 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 245 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
249 | int queue = rx->queue; | ||
250 | |||
251 | /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ | ||
252 | if (rx->queue == NUM_RX_DATA_QUEUES - 1) | ||
253 | queue = 0; | ||
254 | 246 | ||
255 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 247 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
256 | 248 | ||
@@ -271,7 +263,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
271 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 263 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
272 | key, skb->data + hdrlen, | 264 | key, skb->data + hdrlen, |
273 | skb->len - hdrlen, rx->sta->sta.addr, | 265 | skb->len - hdrlen, rx->sta->sta.addr, |
274 | hdr->addr1, hwaccel, queue, | 266 | hdr->addr1, hwaccel, rx->security_idx, |
275 | &rx->tkip_iv32, | 267 | &rx->tkip_iv32, |
276 | &rx->tkip_iv16); | 268 | &rx->tkip_iv16); |
277 | if (res != TKIP_DECRYPT_OK) | 269 | if (res != TKIP_DECRYPT_OK) |
@@ -299,8 +291,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
299 | unsigned int hdrlen; | 291 | unsigned int hdrlen; |
300 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 292 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
301 | 293 | ||
302 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 294 | memset(scratch, 0, 6 * AES_BLOCK_SIZE); |
303 | aad = scratch + 4 * AES_BLOCK_LEN; | 295 | |
296 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | ||
297 | aad = scratch + 4 * AES_BLOCK_SIZE; | ||
304 | 298 | ||
305 | /* | 299 | /* |
306 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) | 300 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
@@ -389,8 +383,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
389 | struct ieee80211_key *key = tx->key; | 383 | struct ieee80211_key *key = tx->key; |
390 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 384 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
391 | int hdrlen, len, tail; | 385 | int hdrlen, len, tail; |
392 | u8 *pos, *pn; | 386 | u8 *pos; |
393 | int i; | 387 | u8 pn[6]; |
388 | u64 pn64; | ||
389 | u8 scratch[6 * AES_BLOCK_SIZE]; | ||
394 | 390 | ||
395 | if (info->control.hw_key && | 391 | if (info->control.hw_key && |
396 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 392 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
@@ -418,14 +414,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
418 | hdr = (struct ieee80211_hdr *) pos; | 414 | hdr = (struct ieee80211_hdr *) pos; |
419 | pos += hdrlen; | 415 | pos += hdrlen; |
420 | 416 | ||
421 | /* PN = PN + 1 */ | 417 | pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn); |
422 | pn = key->u.ccmp.tx_pn; | ||
423 | 418 | ||
424 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { | 419 | pn[5] = pn64; |
425 | pn[i]++; | 420 | pn[4] = pn64 >> 8; |
426 | if (pn[i]) | 421 | pn[3] = pn64 >> 16; |
427 | break; | 422 | pn[2] = pn64 >> 24; |
428 | } | 423 | pn[1] = pn64 >> 32; |
424 | pn[0] = pn64 >> 40; | ||
429 | 425 | ||
430 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 426 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
431 | 427 | ||
@@ -434,8 +430,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
434 | return 0; | 430 | return 0; |
435 | 431 | ||
436 | pos += CCMP_HDR_LEN; | 432 | pos += CCMP_HDR_LEN; |
437 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); | 433 | ccmp_special_blocks(skb, pn, scratch, 0); |
438 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len, | 434 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, |
439 | pos, skb_put(skb, CCMP_MIC_LEN)); | 435 | pos, skb_put(skb, CCMP_MIC_LEN)); |
440 | 436 | ||
441 | return 0; | 437 | return 0; |
@@ -482,8 +478,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
482 | 478 | ||
483 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 479 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
484 | 480 | ||
485 | queue = ieee80211_is_mgmt(hdr->frame_control) ? | 481 | queue = rx->security_idx; |
486 | NUM_RX_DATA_QUEUES : rx->queue; | ||
487 | 482 | ||
488 | if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { | 483 | if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { |
489 | key->u.ccmp.replays++; | 484 | key->u.ccmp.replays++; |
@@ -491,11 +486,12 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
491 | } | 486 | } |
492 | 487 | ||
493 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 488 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
489 | u8 scratch[6 * AES_BLOCK_SIZE]; | ||
494 | /* hardware didn't decrypt/verify MIC */ | 490 | /* hardware didn't decrypt/verify MIC */ |
495 | ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); | 491 | ccmp_special_blocks(skb, pn, scratch, 1); |
496 | 492 | ||
497 | if (ieee80211_aes_ccm_decrypt( | 493 | if (ieee80211_aes_ccm_decrypt( |
498 | key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, | 494 | key->u.ccmp.tfm, scratch, |
499 | skb->data + hdrlen + CCMP_HDR_LEN, data_len, | 495 | skb->data + hdrlen + CCMP_HDR_LEN, data_len, |
500 | skb->data + skb->len - CCMP_MIC_LEN, | 496 | skb->data + skb->len - CCMP_MIC_LEN, |
501 | skb->data + hdrlen + CCMP_HDR_LEN)) | 497 | skb->data + hdrlen + CCMP_HDR_LEN)) |
@@ -526,6 +522,16 @@ static void bip_aad(struct sk_buff *skb, u8 *aad) | |||
526 | } | 522 | } |
527 | 523 | ||
528 | 524 | ||
525 | static inline void bip_ipn_set64(u8 *d, u64 pn) | ||
526 | { | ||
527 | *d++ = pn; | ||
528 | *d++ = pn >> 8; | ||
529 | *d++ = pn >> 16; | ||
530 | *d++ = pn >> 24; | ||
531 | *d++ = pn >> 32; | ||
532 | *d = pn >> 40; | ||
533 | } | ||
534 | |||
529 | static inline void bip_ipn_swap(u8 *d, const u8 *s) | 535 | static inline void bip_ipn_swap(u8 *d, const u8 *s) |
530 | { | 536 | { |
531 | *d++ = s[5]; | 537 | *d++ = s[5]; |
@@ -544,8 +550,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
544 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 550 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
545 | struct ieee80211_key *key = tx->key; | 551 | struct ieee80211_key *key = tx->key; |
546 | struct ieee80211_mmie *mmie; | 552 | struct ieee80211_mmie *mmie; |
547 | u8 *pn, aad[20]; | 553 | u8 aad[20]; |
548 | int i; | 554 | u64 pn64; |
549 | 555 | ||
550 | if (info->control.hw_key) | 556 | if (info->control.hw_key) |
551 | return 0; | 557 | return 0; |
@@ -559,22 +565,17 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
559 | mmie->key_id = cpu_to_le16(key->conf.keyidx); | 565 | mmie->key_id = cpu_to_le16(key->conf.keyidx); |
560 | 566 | ||
561 | /* PN = PN + 1 */ | 567 | /* PN = PN + 1 */ |
562 | pn = key->u.aes_cmac.tx_pn; | 568 | pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn); |
563 | 569 | ||
564 | for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { | 570 | bip_ipn_set64(mmie->sequence_number, pn64); |
565 | pn[i]++; | ||
566 | if (pn[i]) | ||
567 | break; | ||
568 | } | ||
569 | bip_ipn_swap(mmie->sequence_number, pn); | ||
570 | 571 | ||
571 | bip_aad(skb, aad); | 572 | bip_aad(skb, aad); |
572 | 573 | ||
573 | /* | 574 | /* |
574 | * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) | 575 | * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) |
575 | */ | 576 | */ |
576 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, | 577 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, |
577 | aad, skb->data + 24, skb->len - 24, mmie->mic); | 578 | skb->data + 24, skb->len - 24, mmie->mic); |
578 | 579 | ||
579 | return TX_CONTINUE; | 580 | return TX_CONTINUE; |
580 | } | 581 | } |
@@ -612,8 +613,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
612 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 613 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
613 | /* hardware didn't decrypt/verify MIC */ | 614 | /* hardware didn't decrypt/verify MIC */ |
614 | bip_aad(skb, aad); | 615 | bip_aad(skb, aad); |
615 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, | 616 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, |
616 | key->u.aes_cmac.rx_crypto_buf, aad, | ||
617 | skb->data + 24, skb->len - 24, mic); | 617 | skb->data + 24, skb->len - 24, mic); |
618 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { | 618 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { |
619 | key->u.aes_cmac.icverrors++; | 619 | key->u.aes_cmac.icverrors++; |