Blame view
net/wireless/lib80211_crypt_tkip.c
19.2 KB
21042e414 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
b453872c3 [NET] ieee80211 s... |
2 |
/* |
274bfb8dc lib80211: absorb ... |
3 |
* lib80211 crypt: host-based TKIP encryption implementation for lib80211 |
b453872c3 [NET] ieee80211 s... |
4 |
* |
85d32e7b0 [PATCH] Update my... |
5 |
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> |
274bfb8dc lib80211: absorb ... |
6 |
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> |
b453872c3 [NET] ieee80211 s... |
7 |
*/ |
e9c0268f0 net/wireless: Use... |
8 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
f12cc2090 [CRYPTO] users: U... |
9 |
#include <linux/err.h> |
4be297016 net/lib80211: mov... |
10 |
#include <linux/fips.h> |
b453872c3 [NET] ieee80211 s... |
11 12 13 14 |
#include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/random.h> |
117636092 [PATCH] Fix break... |
15 |
#include <linux/scatterlist.h> |
b453872c3 [NET] ieee80211 s... |
16 17 |
#include <linux/skbuff.h> #include <linux/netdevice.h> |
d7fe0f241 [PATCH] severing ... |
18 |
#include <linux/mm.h> |
b453872c3 [NET] ieee80211 s... |
19 20 21 |
#include <linux/if_ether.h> #include <linux/if_arp.h> #include <asm/string.h> |
274bfb8dc lib80211: absorb ... |
22 23 24 |
#include <linux/wireless.h> #include <linux/ieee80211.h> #include <net/iw_handler.h> |
b453872c3 [NET] ieee80211 s... |
25 |
|
4be297016 net/lib80211: mov... |
26 |
#include <crypto/arc4.h> |
608fb34cf lib80211: Use skc... |
27 |
#include <crypto/hash.h> |
b802a5d6f lib80211: don't u... |
28 |
#include <linux/crypto.h> |
b453872c3 [NET] ieee80211 s... |
29 |
#include <linux/crc32.h> |
274bfb8dc lib80211: absorb ... |
30 |
#include <net/lib80211.h> |
b453872c3 [NET] ieee80211 s... |
31 |
MODULE_AUTHOR("Jouni Malinen"); |
274bfb8dc lib80211: absorb ... |
32 |
MODULE_DESCRIPTION("lib80211 crypt: TKIP"); |
b453872c3 [NET] ieee80211 s... |
33 |
MODULE_LICENSE("GPL"); |
299af9d3d lib80211: Introdu... |
34 |
#define TKIP_HDR_LEN 8 |
274bfb8dc lib80211: absorb ... |
35 |
struct lib80211_tkip_data { |
b453872c3 [NET] ieee80211 s... |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
#define TKIP_KEY_LEN 32 u8 key[TKIP_KEY_LEN]; int key_set; u32 tx_iv32; u16 tx_iv16; u16 tx_ttak[5]; int tx_phase1_done; u32 rx_iv32; u16 rx_iv16; u16 rx_ttak[5]; int rx_phase1_done; u32 rx_iv32_new; u16 rx_iv16_new; u32 dot11RSNAStatsTKIPReplays; u32 dot11RSNAStatsTKIPICVErrors; u32 dot11RSNAStatsTKIPLocalMICFailures; int key_idx; |
4be297016 net/lib80211: mov... |
57 58 |
struct arc4_ctx rx_ctx_arc4; struct arc4_ctx tx_ctx_arc4; |
d17504b16 wireless/lib80211... |
59 |
struct crypto_shash *rx_tfm_michael; |
d17504b16 wireless/lib80211... |
60 |
struct crypto_shash *tx_tfm_michael; |
b453872c3 [NET] ieee80211 s... |
61 62 63 |
/* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16], tx_hdr[16]; |
20d64713a [PATCH] ieee80211... |
64 |
|
6eb6edf04 [PATCH] ieee80211... |
65 |
unsigned long flags; |
b453872c3 [NET] ieee80211 s... |
66 |
}; |
274bfb8dc lib80211: absorb ... |
67 |
static unsigned long lib80211_tkip_set_flags(unsigned long flags, void *priv) |
6eb6edf04 [PATCH] ieee80211... |
68 |
{ |
274bfb8dc lib80211: absorb ... |
69 |
struct lib80211_tkip_data *_priv = priv; |
6eb6edf04 [PATCH] ieee80211... |
70 71 72 73 |
unsigned long old_flags = _priv->flags; _priv->flags = flags; return old_flags; } |
274bfb8dc lib80211: absorb ... |
74 |
static unsigned long lib80211_tkip_get_flags(void *priv) |
6eb6edf04 [PATCH] ieee80211... |
75 |
{ |
274bfb8dc lib80211: absorb ... |
76 |
struct lib80211_tkip_data *_priv = priv; |
6eb6edf04 [PATCH] ieee80211... |
77 78 |
return _priv->flags; } |
274bfb8dc lib80211: absorb ... |
79 |
static void *lib80211_tkip_init(int key_idx) |
b453872c3 [NET] ieee80211 s... |
80 |
{ |
274bfb8dc lib80211: absorb ... |
81 |
struct lib80211_tkip_data *priv; |
b453872c3 [NET] ieee80211 s... |
82 |
|
4be297016 net/lib80211: mov... |
83 84 |
if (fips_enabled) return NULL; |
8aa914b74 [PATCH] ieee80211... |
85 |
priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
b453872c3 [NET] ieee80211 s... |
86 87 |
if (priv == NULL) goto fail; |
20d64713a [PATCH] ieee80211... |
88 |
|
b453872c3 [NET] ieee80211 s... |
89 |
priv->key_idx = key_idx; |
d17504b16 wireless/lib80211... |
90 |
priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); |
28eb177df Merge branch 'mas... |
91 |
if (IS_ERR(priv->tx_tfm_michael)) { |
183798799 net/ieee80211: fi... |
92 |
priv->tx_tfm_michael = NULL; |
5a6569497 [PATCH] ieee80211... |
93 94 |
goto fail; } |
d17504b16 wireless/lib80211... |
95 |
priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); |
28eb177df Merge branch 'mas... |
96 |
if (IS_ERR(priv->rx_tfm_michael)) { |
183798799 net/ieee80211: fi... |
97 |
priv->rx_tfm_michael = NULL; |
b453872c3 [NET] ieee80211 s... |
98 99 100 101 |
goto fail; } return priv; |
0edd5b449 [wireless ieee802... |
102 |
fail: |
b453872c3 [NET] ieee80211 s... |
103 |
if (priv) { |
d17504b16 wireless/lib80211... |
104 |
crypto_free_shash(priv->tx_tfm_michael); |
d17504b16 wireless/lib80211... |
105 |
crypto_free_shash(priv->rx_tfm_michael); |
b453872c3 [NET] ieee80211 s... |
106 107 108 109 110 |
kfree(priv); } return NULL; } |
274bfb8dc lib80211: absorb ... |
111 |
static void lib80211_tkip_deinit(void *priv) |
b453872c3 [NET] ieee80211 s... |
112 |
{ |
274bfb8dc lib80211: absorb ... |
113 |
struct lib80211_tkip_data *_priv = priv; |
5a6569497 [PATCH] ieee80211... |
114 |
if (_priv) { |
d17504b16 wireless/lib80211... |
115 |
crypto_free_shash(_priv->tx_tfm_michael); |
d17504b16 wireless/lib80211... |
116 |
crypto_free_shash(_priv->rx_tfm_michael); |
5a6569497 [PATCH] ieee80211... |
117 |
} |
453431a54 mm, treewide: ren... |
118 |
kfree_sensitive(priv); |
b453872c3 [NET] ieee80211 s... |
119 |
} |
b453872c3 [NET] ieee80211 s... |
120 121 122 123 |
static inline u16 RotR1(u16 val) { return (val >> 1) | (val << 15); } |
b453872c3 [NET] ieee80211 s... |
124 125 126 127 |
static inline u8 Lo8(u16 val) { return val & 0xff; } |
b453872c3 [NET] ieee80211 s... |
128 129 130 131 |
static inline u8 Hi8(u16 val) { return val >> 8; } |
b453872c3 [NET] ieee80211 s... |
132 133 134 135 |
static inline u16 Lo16(u32 val) { return val & 0xffff; } |
b453872c3 [NET] ieee80211 s... |
136 137 138 139 |
static inline u16 Hi16(u32 val) { return val >> 16; } |
b453872c3 [NET] ieee80211 s... |
140 141 142 143 |
static inline u16 Mk16(u8 hi, u8 lo) { return lo | (((u16) hi) << 8); } |
d9e94d564 ieee80211: fix mi... |
144 |
static inline u16 Mk16_le(__le16 * v) |
b453872c3 [NET] ieee80211 s... |
145 146 147 |
{ return le16_to_cpu(*v); } |
0edd5b449 [wireless ieee802... |
148 |
static const u16 Sbox[256] = { |
b453872c3 [NET] ieee80211 s... |
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, }; |
b453872c3 [NET] ieee80211 s... |
182 183 184 185 186 |
static inline u16 _S_(u16 v) { u16 t = Sbox[Hi8(v)]; return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); } |
b453872c3 [NET] ieee80211 s... |
187 |
#define PHASE1_LOOP_COUNT 8 |
0edd5b449 [wireless ieee802... |
188 189 |
static void tkip_mixing_phase1(u16 * TTAK, const u8 * TK, const u8 * TA, u32 IV32) |
b453872c3 [NET] ieee80211 s... |
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
{ int i, j; /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ TTAK[0] = Lo16(IV32); TTAK[1] = Hi16(IV32); TTAK[2] = Mk16(TA[1], TA[0]); TTAK[3] = Mk16(TA[3], TA[2]); TTAK[4] = Mk16(TA[5], TA[4]); for (i = 0; i < PHASE1_LOOP_COUNT; i++) { j = 2 * (i & 1); TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; } } |
0edd5b449 [wireless ieee802... |
209 |
static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK, |
b453872c3 [NET] ieee80211 s... |
210 211 212 213 |
u16 IV16) { /* Make temporary area overlap WEP seed so that the final copy can be * avoided on little endian hosts. */ |
0edd5b449 [wireless ieee802... |
214 |
u16 *PPK = (u16 *) & WEPSeed[4]; |
b453872c3 [NET] ieee80211 s... |
215 216 217 218 219 220 221 222 223 224 |
/* Step 1 - make copy of TTAK and bring in TSC */ PPK[0] = TTAK[0]; PPK[1] = TTAK[1]; PPK[2] = TTAK[2]; PPK[3] = TTAK[3]; PPK[4] = TTAK[4]; PPK[5] = TTAK[4] + IV16; /* Step 2 - 96-bit bijective mixing using S-box */ |
d9e94d564 ieee80211: fix mi... |
225 226 227 228 229 230 231 232 233 |
PPK[0] += _S_(PPK[5] ^ Mk16_le((__le16 *) & TK[0])); PPK[1] += _S_(PPK[0] ^ Mk16_le((__le16 *) & TK[2])); PPK[2] += _S_(PPK[1] ^ Mk16_le((__le16 *) & TK[4])); PPK[3] += _S_(PPK[2] ^ Mk16_le((__le16 *) & TK[6])); PPK[4] += _S_(PPK[3] ^ Mk16_le((__le16 *) & TK[8])); PPK[5] += _S_(PPK[4] ^ Mk16_le((__le16 *) & TK[10])); PPK[0] += RotR1(PPK[5] ^ Mk16_le((__le16 *) & TK[12])); PPK[1] += RotR1(PPK[0] ^ Mk16_le((__le16 *) & TK[14])); |
b453872c3 [NET] ieee80211 s... |
234 235 236 237 238 239 240 241 242 243 |
PPK[2] += RotR1(PPK[1]); PPK[3] += RotR1(PPK[2]); PPK[4] += RotR1(PPK[3]); PPK[5] += RotR1(PPK[4]); /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value * WEPSeed[0..2] is transmitted as WEP IV */ WEPSeed[0] = Hi8(IV16); WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; WEPSeed[2] = Lo8(IV16); |
d9e94d564 ieee80211: fix mi... |
244 |
WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((__le16 *) & TK[0])) >> 1); |
b453872c3 [NET] ieee80211 s... |
245 246 247 248 249 250 251 252 253 |
#ifdef __BIG_ENDIAN { int i; for (i = 0; i < 6; i++) PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); } #endif } |
274bfb8dc lib80211: absorb ... |
254 |
static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, |
9184d9348 [PATCH] ieee80211... |
255 |
u8 * rc4key, int keylen, void *priv) |
b453872c3 [NET] ieee80211 s... |
256 |
{ |
274bfb8dc lib80211: absorb ... |
257 |
struct lib80211_tkip_data *tkey = priv; |
9184d9348 [PATCH] ieee80211... |
258 |
u8 *pos; |
274bfb8dc lib80211: absorb ... |
259 |
struct ieee80211_hdr *hdr; |
b453872c3 [NET] ieee80211 s... |
260 |
|
274bfb8dc lib80211: absorb ... |
261 |
hdr = (struct ieee80211_hdr *)skb->data; |
20d64713a [PATCH] ieee80211... |
262 |
|
299af9d3d lib80211: Introdu... |
263 |
if (skb_headroom(skb) < TKIP_HDR_LEN || skb->len < hdr_len) |
9184d9348 [PATCH] ieee80211... |
264 265 266 267 |
return -1; if (rc4key == NULL || keylen < 16) return -1; |
b453872c3 [NET] ieee80211 s... |
268 |
|
b453872c3 [NET] ieee80211 s... |
269 270 271 272 273 274 |
if (!tkey->tx_phase1_done) { tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, tkey->tx_iv32); tkey->tx_phase1_done = 1; } tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); |
299af9d3d lib80211: Introdu... |
275 276 |
pos = skb_push(skb, TKIP_HDR_LEN); memmove(pos, pos + TKIP_HDR_LEN, hdr_len); |
b453872c3 [NET] ieee80211 s... |
277 |
pos += hdr_len; |
b453872c3 [NET] ieee80211 s... |
278 |
|
31b59eaee [PATCH] ieee80211... |
279 280 281 |
*pos++ = *rc4key; *pos++ = *(rc4key + 1); *pos++ = *(rc4key + 2); |
0edd5b449 [wireless ieee802... |
282 |
*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ; |
b453872c3 [NET] ieee80211 s... |
283 284 285 286 |
*pos++ = tkey->tx_iv32 & 0xff; *pos++ = (tkey->tx_iv32 >> 8) & 0xff; *pos++ = (tkey->tx_iv32 >> 16) & 0xff; *pos++ = (tkey->tx_iv32 >> 24) & 0xff; |
9184d9348 [PATCH] ieee80211... |
287 288 289 290 291 |
tkey->tx_iv16++; if (tkey->tx_iv16 == 0) { tkey->tx_phase1_done = 0; tkey->tx_iv32++; } |
b453872c3 [NET] ieee80211 s... |
292 |
|
299af9d3d lib80211: Introdu... |
293 |
return TKIP_HDR_LEN; |
31b59eaee [PATCH] ieee80211... |
294 |
} |
274bfb8dc lib80211: absorb ... |
295 |
static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
31b59eaee [PATCH] ieee80211... |
296 |
{ |
274bfb8dc lib80211: absorb ... |
297 |
struct lib80211_tkip_data *tkey = priv; |
31b59eaee [PATCH] ieee80211... |
298 |
int len; |
9184d9348 [PATCH] ieee80211... |
299 300 |
u8 rc4key[16], *pos, *icv; u32 crc; |
31b59eaee [PATCH] ieee80211... |
301 |
|
6eb6edf04 [PATCH] ieee80211... |
302 |
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { |
e87cc4728 net: Convert net_... |
303 304 305 306 |
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; net_dbg_ratelimited("TKIP countermeasures: dropped TX packet to %pM ", hdr->addr1); |
31b59eaee [PATCH] ieee80211... |
307 308 309 310 311 312 313 314 |
return -1; } if (skb_tailroom(skb) < 4 || skb->len < hdr_len) return -1; len = skb->len - hdr_len; pos = skb->data + hdr_len; |
274bfb8dc lib80211: absorb ... |
315 |
if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) |
31b59eaee [PATCH] ieee80211... |
316 |
return -1; |
9184d9348 [PATCH] ieee80211... |
317 |
crc = ~crc32_le(~0, pos, len); |
d0833a6a2 lib80211: Cosmeti... |
318 |
icv = skb_put(skb, 4); |
9184d9348 [PATCH] ieee80211... |
319 320 321 322 |
icv[0] = crc; icv[1] = crc >> 8; icv[2] = crc >> 16; icv[3] = crc >> 24; |
4be297016 net/lib80211: mov... |
323 324 |
arc4_setkey(&tkey->tx_ctx_arc4, rc4key, 16); arc4_crypt(&tkey->tx_ctx_arc4, pos, pos, len + 4); |
b802a5d6f lib80211: don't u... |
325 |
return 0; |
b4328d87e [PATCH] ieee80211... |
326 |
} |
183798799 net/ieee80211: fi... |
327 328 329 330 331 332 333 334 335 336 337 338 |
/* * deal with seq counter wrapping correctly. * refer to timer_after() for jiffies wrapping handling */ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, u32 iv32_o, u16 iv16_o) { if ((s32)iv32_n - (s32)iv32_o < 0 || (iv32_n == iv32_o && iv16_n <= iv16_o)) return 1; return 0; } |
274bfb8dc lib80211: absorb ... |
339 |
static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
b453872c3 [NET] ieee80211 s... |
340 |
{ |
274bfb8dc lib80211: absorb ... |
341 |
struct lib80211_tkip_data *tkey = priv; |
b453872c3 [NET] ieee80211 s... |
342 343 344 345 |
u8 rc4key[16]; u8 keyidx, *pos; u32 iv32; u16 iv16; |
274bfb8dc lib80211: absorb ... |
346 |
struct ieee80211_hdr *hdr; |
b453872c3 [NET] ieee80211 s... |
347 348 |
u8 icv[4]; u32 crc; |
b453872c3 [NET] ieee80211 s... |
349 |
int plen; |
274bfb8dc lib80211: absorb ... |
350 |
hdr = (struct ieee80211_hdr *)skb->data; |
20d64713a [PATCH] ieee80211... |
351 |
|
6eb6edf04 [PATCH] ieee80211... |
352 |
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { |
e87cc4728 net: Convert net_... |
353 354 355 |
net_dbg_ratelimited("TKIP countermeasures: dropped received packet from %pM ", hdr->addr2); |
20d64713a [PATCH] ieee80211... |
356 357 |
return -1; } |
299af9d3d lib80211: Introdu... |
358 |
if (skb->len < hdr_len + TKIP_HDR_LEN + 4) |
b453872c3 [NET] ieee80211 s... |
359 |
return -1; |
b453872c3 [NET] ieee80211 s... |
360 361 362 |
pos = skb->data + hdr_len; keyidx = pos[3]; if (!(keyidx & (1 << 5))) { |
e87cc4728 net: Convert net_... |
363 364 365 |
net_dbg_ratelimited("TKIP: received packet without ExtIV flag from %pM ", hdr->addr2); |
b453872c3 [NET] ieee80211 s... |
366 367 368 369 |
return -2; } keyidx >>= 6; if (tkey->key_idx != keyidx) { |
996bf99c7 lib80211: ratelim... |
370 371 372 |
net_dbg_ratelimited("TKIP: RX tkey->key_idx=%d frame keyidx=%d ", tkey->key_idx, keyidx); |
b453872c3 [NET] ieee80211 s... |
373 374 375 |
return -6; } if (!tkey->key_set) { |
e87cc4728 net: Convert net_... |
376 377 378 |
net_dbg_ratelimited("TKIP: received packet from %pM with keyid=%d that does not have a configured key ", hdr->addr2, keyidx); |
b453872c3 [NET] ieee80211 s... |
379 380 381 382 |
return -3; } iv16 = (pos[0] << 8) | pos[2]; iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); |
299af9d3d lib80211: Introdu... |
383 |
pos += TKIP_HDR_LEN; |
b453872c3 [NET] ieee80211 s... |
384 |
|
b4328d87e [PATCH] ieee80211... |
385 |
if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { |
6f16bf3bd lib80211: silence... |
386 |
#ifdef CONFIG_LIB80211_DEBUG |
e87cc4728 net: Convert net_... |
387 388 389 390 |
net_dbg_ratelimited("TKIP: replay detected: STA=%pM previous TSC %08x%04x received TSC %08x%04x ", hdr->addr2, tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); |
6f16bf3bd lib80211: silence... |
391 |
#endif |
b453872c3 [NET] ieee80211 s... |
392 393 394 395 396 397 398 399 400 401 402 |
tkey->dot11RSNAStatsTKIPReplays++; return -4; } if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); tkey->rx_phase1_done = 1; } tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); plen = skb->len - hdr_len - 12; |
4be297016 net/lib80211: mov... |
403 404 |
arc4_setkey(&tkey->rx_ctx_arc4, rc4key, 16); arc4_crypt(&tkey->rx_ctx_arc4, pos, pos, plen + 4); |
b453872c3 [NET] ieee80211 s... |
405 406 407 408 409 410 411 412 413 414 415 416 |
crc = ~crc32_le(~0, pos, plen); icv[0] = crc; icv[1] = crc >> 8; icv[2] = crc >> 16; icv[3] = crc >> 24; if (memcmp(icv, pos + plen, 4) != 0) { if (iv32 != tkey->rx_iv32) { /* Previously cached Phase1 result was already lost, so * it needs to be recalculated for the next packet. */ tkey->rx_phase1_done = 0; } |
6f16bf3bd lib80211: silence... |
417 |
#ifdef CONFIG_LIB80211_DEBUG |
e87cc4728 net: Convert net_... |
418 419 420 |
net_dbg_ratelimited("TKIP: ICV error detected: STA=%pM ", hdr->addr2); |
6f16bf3bd lib80211: silence... |
421 |
#endif |
b453872c3 [NET] ieee80211 s... |
422 423 424 425 426 427 428 429 430 431 |
tkey->dot11RSNAStatsTKIPICVErrors++; return -5; } /* Update real counters only after Michael MIC verification has * completed */ tkey->rx_iv32_new = iv32; tkey->rx_iv16_new = iv16; /* Remove IV and ICV */ |
299af9d3d lib80211: Introdu... |
432 433 |
memmove(skb->data + TKIP_HDR_LEN, skb->data, hdr_len); skb_pull(skb, TKIP_HDR_LEN); |
b453872c3 [NET] ieee80211 s... |
434 435 436 437 |
skb_trim(skb, skb->len - 4); return keyidx; } |
d17504b16 wireless/lib80211... |
438 439 |
static int michael_mic(struct crypto_shash *tfm_michael, u8 *key, u8 *hdr, u8 *data, size_t data_len, u8 *mic) |
b453872c3 [NET] ieee80211 s... |
440 |
{ |
d17504b16 wireless/lib80211... |
441 |
SHASH_DESC_ON_STACK(desc, tfm_michael); |
608fb34cf lib80211: Use skc... |
442 |
int err; |
b453872c3 [NET] ieee80211 s... |
443 |
|
5a6569497 [PATCH] ieee80211... |
444 |
if (tfm_michael == NULL) { |
e9c0268f0 net/wireless: Use... |
445 446 |
pr_warn("%s(): tfm_michael == NULL ", __func__); |
b453872c3 [NET] ieee80211 s... |
447 448 |
return -1; } |
b453872c3 [NET] ieee80211 s... |
449 |
|
d17504b16 wireless/lib80211... |
450 |
desc->tfm = tfm_michael; |
d17504b16 wireless/lib80211... |
451 452 |
if (crypto_shash_setkey(tfm_michael, key, 8)) |
350586879 [CRYPTO] users: U... |
453 |
return -1; |
b453872c3 [NET] ieee80211 s... |
454 |
|
d17504b16 wireless/lib80211... |
455 456 457 458 459 460 461 462 463 464 465 466 467 |
err = crypto_shash_init(desc); if (err) goto out; err = crypto_shash_update(desc, hdr, 16); if (err) goto out; err = crypto_shash_update(desc, data, data_len); if (err) goto out; err = crypto_shash_final(desc, mic); out: shash_desc_zero(desc); |
608fb34cf lib80211: Use skc... |
468 |
return err; |
b453872c3 [NET] ieee80211 s... |
469 |
} |
0edd5b449 [wireless ieee802... |
470 |
static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) |
b453872c3 [NET] ieee80211 s... |
471 |
{ |
274bfb8dc lib80211: absorb ... |
472 |
struct ieee80211_hdr *hdr11; |
b453872c3 [NET] ieee80211 s... |
473 |
|
274bfb8dc lib80211: absorb ... |
474 |
hdr11 = (struct ieee80211_hdr *)skb->data; |
ea2841521 [PATCH] ieee80211... |
475 |
|
274bfb8dc lib80211: absorb ... |
476 |
switch (le16_to_cpu(hdr11->frame_control) & |
b453872c3 [NET] ieee80211 s... |
477 478 |
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { case IEEE80211_FCTL_TODS: |
0edd5b449 [wireless ieee802... |
479 480 |
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ |
b453872c3 [NET] ieee80211 s... |
481 482 |
break; case IEEE80211_FCTL_FROMDS: |
0edd5b449 [wireless ieee802... |
483 484 |
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ |
b453872c3 [NET] ieee80211 s... |
485 486 |
break; case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: |
0edd5b449 [wireless ieee802... |
487 488 |
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ |
b453872c3 [NET] ieee80211 s... |
489 |
break; |
10f3366b4 wireless: fix bog... |
490 |
default: |
0edd5b449 [wireless ieee802... |
491 492 |
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ |
b453872c3 [NET] ieee80211 s... |
493 494 |
break; } |
274bfb8dc lib80211: absorb ... |
495 |
if (ieee80211_is_data_qos(hdr11->frame_control)) { |
3f6ff6bac wireless: correct... |
496 |
hdr[12] = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(hdr11))) |
274bfb8dc lib80211: absorb ... |
497 |
& IEEE80211_QOS_CTL_TID_MASK; |
ea2841521 [PATCH] ieee80211... |
498 499 |
} else hdr[12] = 0; /* priority */ |
0edd5b449 [wireless ieee802... |
500 |
hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ |
b453872c3 [NET] ieee80211 s... |
501 |
} |
274bfb8dc lib80211: absorb ... |
502 |
static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len, |
0edd5b449 [wireless ieee802... |
503 |
void *priv) |
b453872c3 [NET] ieee80211 s... |
504 |
{ |
274bfb8dc lib80211: absorb ... |
505 |
struct lib80211_tkip_data *tkey = priv; |
b453872c3 [NET] ieee80211 s... |
506 507 508 509 510 511 512 513 514 515 516 517 |
u8 *pos; if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { printk(KERN_DEBUG "Invalid packet for Michael MIC add " "(tailroom=%d hdr_len=%d skb->len=%d) ", skb_tailroom(skb), hdr_len, skb->len); return -1; } michael_mic_hdr(skb, tkey->tx_hdr); pos = skb_put(skb, 8); |
5a6569497 [PATCH] ieee80211... |
518 |
if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, |
b453872c3 [NET] ieee80211 s... |
519 520 521 522 523 |
skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) return -1; return 0; } |
274bfb8dc lib80211: absorb ... |
524 525 |
static void lib80211_michael_mic_failure(struct net_device *dev, struct ieee80211_hdr *hdr, |
ee34af37c [PATCH] ieee80211... |
526 |
int keyidx) |
b453872c3 [NET] ieee80211 s... |
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 |
{ union iwreq_data wrqu; struct iw_michaelmicfailure ev; /* TODO: needed parameters: count, keyid, key type, TSC */ memset(&ev, 0, sizeof(ev)); ev.flags = keyidx & IW_MICFAILURE_KEY_ID; if (hdr->addr1[0] & 0x01) ev.flags |= IW_MICFAILURE_GROUP; else ev.flags |= IW_MICFAILURE_PAIRWISE; ev.src_addr.sa_family = ARPHRD_ETHER; memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = sizeof(ev); |
0edd5b449 [wireless ieee802... |
542 |
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); |
b453872c3 [NET] ieee80211 s... |
543 |
} |
b453872c3 [NET] ieee80211 s... |
544 |
|
274bfb8dc lib80211: absorb ... |
545 |
static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx, |
0edd5b449 [wireless ieee802... |
546 |
int hdr_len, void *priv) |
b453872c3 [NET] ieee80211 s... |
547 |
{ |
274bfb8dc lib80211: absorb ... |
548 |
struct lib80211_tkip_data *tkey = priv; |
b453872c3 [NET] ieee80211 s... |
549 550 551 552 553 554 |
u8 mic[8]; if (!tkey->key_set) return -1; michael_mic_hdr(skb, tkey->rx_hdr); |
5a6569497 [PATCH] ieee80211... |
555 |
if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, |
b453872c3 [NET] ieee80211 s... |
556 557 558 |
skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) return -1; if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { |
274bfb8dc lib80211: absorb ... |
559 560 |
struct ieee80211_hdr *hdr; hdr = (struct ieee80211_hdr *)skb->data; |
b453872c3 [NET] ieee80211 s... |
561 |
printk(KERN_DEBUG "%s: Michael MIC verification failed for " |
e174961ca net: convert prin... |
562 563 564 |
"MSDU from %pM keyidx=%d ", skb->dev ? skb->dev->name : "N/A", hdr->addr2, |
b453872c3 [NET] ieee80211 s... |
565 566 |
keyidx); if (skb->dev) |
274bfb8dc lib80211: absorb ... |
567 |
lib80211_michael_mic_failure(skb->dev, hdr, keyidx); |
b453872c3 [NET] ieee80211 s... |
568 569 570 571 572 573 574 575 576 577 578 579 580 |
tkey->dot11RSNAStatsTKIPLocalMICFailures++; return -1; } /* Update TSC counters for RX now that the packet verification has * completed. */ tkey->rx_iv32 = tkey->rx_iv32_new; tkey->rx_iv16 = tkey->rx_iv16_new; skb_trim(skb, skb->len - 8); return 0; } |
274bfb8dc lib80211: absorb ... |
581 |
static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) |
b453872c3 [NET] ieee80211 s... |
582 |
{ |
274bfb8dc lib80211: absorb ... |
583 |
struct lib80211_tkip_data *tkey = priv; |
b453872c3 [NET] ieee80211 s... |
584 |
int keyidx; |
d17504b16 wireless/lib80211... |
585 |
struct crypto_shash *tfm = tkey->tx_tfm_michael; |
4be297016 net/lib80211: mov... |
586 |
struct arc4_ctx *tfm2 = &tkey->tx_ctx_arc4; |
d17504b16 wireless/lib80211... |
587 |
struct crypto_shash *tfm3 = tkey->rx_tfm_michael; |
4be297016 net/lib80211: mov... |
588 |
struct arc4_ctx *tfm4 = &tkey->rx_ctx_arc4; |
b453872c3 [NET] ieee80211 s... |
589 590 591 592 |
keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); tkey->key_idx = keyidx; |
5a6569497 [PATCH] ieee80211... |
593 |
tkey->tx_tfm_michael = tfm; |
4be297016 net/lib80211: mov... |
594 |
tkey->tx_ctx_arc4 = *tfm2; |
5a6569497 [PATCH] ieee80211... |
595 |
tkey->rx_tfm_michael = tfm3; |
4be297016 net/lib80211: mov... |
596 |
tkey->rx_ctx_arc4 = *tfm4; |
b453872c3 [NET] ieee80211 s... |
597 598 599 |
if (len == TKIP_KEY_LEN) { memcpy(tkey->key, key, TKIP_KEY_LEN); tkey->key_set = 1; |
0edd5b449 [wireless ieee802... |
600 |
tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ |
b453872c3 [NET] ieee80211 s... |
601 602 |
if (seq) { tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | |
0edd5b449 [wireless ieee802... |
603 |
(seq[3] << 8) | seq[2]; |
b453872c3 [NET] ieee80211 s... |
604 605 606 607 608 609 610 611 612 |
tkey->rx_iv16 = (seq[1] << 8) | seq[0]; } } else if (len == 0) tkey->key_set = 0; else return -1; return 0; } |
274bfb8dc lib80211: absorb ... |
613 |
static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv) |
b453872c3 [NET] ieee80211 s... |
614 |
{ |
274bfb8dc lib80211: absorb ... |
615 |
struct lib80211_tkip_data *tkey = priv; |
b453872c3 [NET] ieee80211 s... |
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 |
if (len < TKIP_KEY_LEN) return -1; if (!tkey->key_set) return 0; memcpy(key, tkey->key, TKIP_KEY_LEN); if (seq) { /* Return the sequence number of the last transmitted frame. */ u16 iv16 = tkey->tx_iv16; u32 iv32 = tkey->tx_iv32; if (iv16 == 0) iv32--; iv16--; seq[0] = tkey->tx_iv16; seq[1] = tkey->tx_iv16 >> 8; seq[2] = tkey->tx_iv32; seq[3] = tkey->tx_iv32 >> 8; seq[4] = tkey->tx_iv32 >> 16; seq[5] = tkey->tx_iv32 >> 24; } return TKIP_KEY_LEN; } |
6bbefe867 hostap: Don't use... |
641 |
static void lib80211_tkip_print_stats(struct seq_file *m, void *priv) |
b453872c3 [NET] ieee80211 s... |
642 |
{ |
274bfb8dc lib80211: absorb ... |
643 |
struct lib80211_tkip_data *tkip = priv; |
6bbefe867 hostap: Don't use... |
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 |
seq_printf(m, "key[%d] alg=TKIP key_set=%d " "tx_pn=%02x%02x%02x%02x%02x%02x " "rx_pn=%02x%02x%02x%02x%02x%02x " "replays=%d icv_errors=%d local_mic_failures=%d ", tkip->key_idx, tkip->key_set, (tkip->tx_iv32 >> 24) & 0xff, (tkip->tx_iv32 >> 16) & 0xff, (tkip->tx_iv32 >> 8) & 0xff, tkip->tx_iv32 & 0xff, (tkip->tx_iv16 >> 8) & 0xff, tkip->tx_iv16 & 0xff, (tkip->rx_iv32 >> 24) & 0xff, (tkip->rx_iv32 >> 16) & 0xff, (tkip->rx_iv32 >> 8) & 0xff, tkip->rx_iv32 & 0xff, (tkip->rx_iv16 >> 8) & 0xff, tkip->rx_iv16 & 0xff, tkip->dot11RSNAStatsTKIPReplays, tkip->dot11RSNAStatsTKIPICVErrors, tkip->dot11RSNAStatsTKIPLocalMICFailures); |
b453872c3 [NET] ieee80211 s... |
666 |
} |
274bfb8dc lib80211: absorb ... |
667 |
static struct lib80211_crypto_ops lib80211_crypt_tkip = { |
74079fdce [PATCH] ieee80211... |
668 |
.name = "TKIP", |
274bfb8dc lib80211: absorb ... |
669 670 |
.init = lib80211_tkip_init, .deinit = lib80211_tkip_deinit, |
274bfb8dc lib80211: absorb ... |
671 672 673 674 675 676 677 |
.encrypt_mpdu = lib80211_tkip_encrypt, .decrypt_mpdu = lib80211_tkip_decrypt, .encrypt_msdu = lib80211_michael_mic_add, .decrypt_msdu = lib80211_michael_mic_verify, .set_key = lib80211_tkip_set_key, .get_key = lib80211_tkip_get_key, .print_stats = lib80211_tkip_print_stats, |
1264fc049 [PATCH] ieee80211... |
678 679 680 |
.extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */ .extra_mpdu_postfix_len = 4, /* ICV */ .extra_msdu_postfix_len = 8, /* MIC */ |
274bfb8dc lib80211: absorb ... |
681 682 |
.get_flags = lib80211_tkip_get_flags, .set_flags = lib80211_tkip_set_flags, |
74079fdce [PATCH] ieee80211... |
683 |
.owner = THIS_MODULE, |
b453872c3 [NET] ieee80211 s... |
684 |
}; |
274bfb8dc lib80211: absorb ... |
685 |
static int __init lib80211_crypto_tkip_init(void) |
b453872c3 [NET] ieee80211 s... |
686 |
{ |
274bfb8dc lib80211: absorb ... |
687 |
return lib80211_register_crypto_ops(&lib80211_crypt_tkip); |
b453872c3 [NET] ieee80211 s... |
688 |
} |
274bfb8dc lib80211: absorb ... |
689 |
static void __exit lib80211_crypto_tkip_exit(void) |
b453872c3 [NET] ieee80211 s... |
690 |
{ |
274bfb8dc lib80211: absorb ... |
691 |
lib80211_unregister_crypto_ops(&lib80211_crypt_tkip); |
b453872c3 [NET] ieee80211 s... |
692 |
} |
274bfb8dc lib80211: absorb ... |
693 694 |
module_init(lib80211_crypto_tkip_init); module_exit(lib80211_crypto_tkip_exit); |