aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_crypt_tkip.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_tkip.c')
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c53
1 files changed, 27 insertions, 26 deletions
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index de56a47edb00..93def94c1b32 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -270,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
270#endif 270#endif
271} 271}
272 272
273static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv) 273static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
274 u8 * rc4key, int keylen, void *priv)
274{ 275{
275 struct ieee80211_tkip_data *tkey = priv; 276 struct ieee80211_tkip_data *tkey = priv;
276 int len; 277 int len;
277 u8 *rc4key, *pos, *icv; 278 u8 *pos;
278 struct ieee80211_hdr_4addr *hdr; 279 struct ieee80211_hdr_4addr *hdr;
279 u32 crc;
280 280
281 hdr = (struct ieee80211_hdr_4addr *)skb->data; 281 hdr = (struct ieee80211_hdr_4addr *)skb->data;
282 282
283 if (skb_headroom(skb) < 8 || skb->len < hdr_len) 283 if (skb_headroom(skb) < 8 || skb->len < hdr_len)
284 return NULL; 284 return -1;
285
286 if (rc4key == NULL || keylen < 16)
287 return -1;
285 288
286 if (!tkey->tx_phase1_done) { 289 if (!tkey->tx_phase1_done) {
287 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, 290 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
288 tkey->tx_iv32); 291 tkey->tx_iv32);
289 tkey->tx_phase1_done = 1; 292 tkey->tx_phase1_done = 1;
290 } 293 }
291 rc4key = kmalloc(16, GFP_ATOMIC);
292 if (!rc4key)
293 return NULL;
294 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); 294 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
295 295
296 len = skb->len - hdr_len; 296 len = skb->len - hdr_len;
297 pos = skb_push(skb, 8); 297 pos = skb_push(skb, 8);
298 memmove(pos, pos + 8, hdr_len); 298 memmove(pos, pos + 8, hdr_len);
299 pos += hdr_len; 299 pos += hdr_len;
300 icv = skb_put(skb, 4);
301 300
302 *pos++ = *rc4key; 301 *pos++ = *rc4key;
303 *pos++ = *(rc4key + 1); 302 *pos++ = *(rc4key + 1);
@@ -308,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
308 *pos++ = (tkey->tx_iv32 >> 16) & 0xff; 307 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
309 *pos++ = (tkey->tx_iv32 >> 24) & 0xff; 308 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
310 309
311 crc = ~crc32_le(~0, pos, len); 310 tkey->tx_iv16++;
312 icv[0] = crc; 311 if (tkey->tx_iv16 == 0) {
313 icv[1] = crc >> 8; 312 tkey->tx_phase1_done = 0;
314 icv[2] = crc >> 16; 313 tkey->tx_iv32++;
315 icv[3] = crc >> 24; 314 }
316 315
317 return rc4key; 316 return 8;
318} 317}
319 318
320static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 319static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
321{ 320{
322 struct ieee80211_tkip_data *tkey = priv; 321 struct ieee80211_tkip_data *tkey = priv;
323 int len; 322 int len;
324 const u8 *rc4key; 323 u8 rc4key[16], *pos, *icv;
325 u8 *pos; 324 u32 crc;
326 struct scatterlist sg; 325 struct scatterlist sg;
327 326
328 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { 327 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
329 if (net_ratelimit()) { 328 if (net_ratelimit()) {
330 struct ieee80211_hdr_4addr *hdr = 329 struct ieee80211_hdr_4addr *hdr =
331 (struct ieee80211_hdr_4addr *)skb->data; 330 (struct ieee80211_hdr_4addr *)skb->data;
332 printk(KERN_DEBUG "TKIP countermeasures: dropped " 331 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
333 "TX packet to " MAC_FMT "\n", 332 "TX packet to " MAC_FMT "\n",
334 MAC_ARG(hdr->addr1)); 333 MAC_ARG(hdr->addr1));
335 } 334 }
@@ -342,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
342 len = skb->len - hdr_len; 341 len = skb->len - hdr_len;
343 pos = skb->data + hdr_len; 342 pos = skb->data + hdr_len;
344 343
345 rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv); 344 if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
346 if (!rc4key)
347 return -1; 345 return -1;
348 346
347 icv = skb_put(skb, 4);
348
349 crc = ~crc32_le(~0, pos, len);
350 icv[0] = crc;
351 icv[1] = crc >> 8;
352 icv[2] = crc >> 16;
353 icv[3] = crc >> 24;
354
349 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 355 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
350 sg.page = virt_to_page(pos); 356 sg.page = virt_to_page(pos);
351 sg.offset = offset_in_page(pos); 357 sg.offset = offset_in_page(pos);
352 sg.length = len + 4; 358 sg.length = len + 4;
353 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); 359 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
354 360
355 tkey->tx_iv16++;
356 if (tkey->tx_iv16 == 0) {
357 tkey->tx_phase1_done = 0;
358 tkey->tx_iv32++;
359 }
360
361 return 0; 361 return 0;
362} 362}
363 363
@@ -378,7 +378,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
378 378
379 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { 379 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
380 if (net_ratelimit()) { 380 if (net_ratelimit()) {
381 printk(KERN_DEBUG "TKIP countermeasures: dropped " 381 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
382 "received packet from " MAC_FMT "\n", 382 "received packet from " MAC_FMT "\n",
383 MAC_ARG(hdr->addr2)); 383 MAC_ARG(hdr->addr2));
384 } 384 }
@@ -694,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
694 .name = "TKIP", 694 .name = "TKIP",
695 .init = ieee80211_tkip_init, 695 .init = ieee80211_tkip_init,
696 .deinit = ieee80211_tkip_deinit, 696 .deinit = ieee80211_tkip_deinit,
697 .build_iv = ieee80211_tkip_hdr,
697 .encrypt_mpdu = ieee80211_tkip_encrypt, 698 .encrypt_mpdu = ieee80211_tkip_encrypt,
698 .decrypt_mpdu = ieee80211_tkip_decrypt, 699 .decrypt_mpdu = ieee80211_tkip_decrypt,
699 .encrypt_msdu = ieee80211_michael_mic_add, 700 .encrypt_msdu = ieee80211_michael_mic_add,