diff options
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_tkip.c')
-rw-r--r-- | net/ieee80211/ieee80211_crypt_tkip.c | 150 |
1 files changed, 96 insertions, 54 deletions
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index d4f9164be1a1..2e34f29b7956 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c | |||
@@ -59,8 +59,24 @@ struct ieee80211_tkip_data { | |||
59 | 59 | ||
60 | /* scratch buffers for virt_to_page() (crypto API) */ | 60 | /* scratch buffers for virt_to_page() (crypto API) */ |
61 | u8 rx_hdr[16], tx_hdr[16]; | 61 | u8 rx_hdr[16], tx_hdr[16]; |
62 | |||
63 | unsigned long flags; | ||
62 | }; | 64 | }; |
63 | 65 | ||
66 | static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv) | ||
67 | { | ||
68 | struct ieee80211_tkip_data *_priv = priv; | ||
69 | unsigned long old_flags = _priv->flags; | ||
70 | _priv->flags = flags; | ||
71 | return old_flags; | ||
72 | } | ||
73 | |||
74 | static unsigned long ieee80211_tkip_get_flags(void *priv) | ||
75 | { | ||
76 | struct ieee80211_tkip_data *_priv = priv; | ||
77 | return _priv->flags; | ||
78 | } | ||
79 | |||
64 | static void *ieee80211_tkip_init(int key_idx) | 80 | static void *ieee80211_tkip_init(int key_idx) |
65 | { | 81 | { |
66 | struct ieee80211_tkip_data *priv; | 82 | struct ieee80211_tkip_data *priv; |
@@ -69,6 +85,7 @@ static void *ieee80211_tkip_init(int key_idx) | |||
69 | if (priv == NULL) | 85 | if (priv == NULL) |
70 | goto fail; | 86 | goto fail; |
71 | memset(priv, 0, sizeof(*priv)); | 87 | memset(priv, 0, sizeof(*priv)); |
88 | |||
72 | priv->key_idx = key_idx; | 89 | priv->key_idx = key_idx; |
73 | 90 | ||
74 | priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); | 91 | priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); |
@@ -255,25 +272,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK, | |||
255 | #endif | 272 | #endif |
256 | } | 273 | } |
257 | 274 | ||
258 | static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 275 | static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv) |
259 | { | 276 | { |
260 | struct ieee80211_tkip_data *tkey = priv; | 277 | struct ieee80211_tkip_data *tkey = priv; |
261 | int len; | 278 | int len; |
262 | u8 rc4key[16], *pos, *icv; | 279 | u8 *rc4key, *pos, *icv; |
263 | struct ieee80211_hdr *hdr; | 280 | struct ieee80211_hdr_4addr *hdr; |
264 | u32 crc; | 281 | u32 crc; |
265 | struct scatterlist sg; | ||
266 | 282 | ||
267 | if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || | 283 | hdr = (struct ieee80211_hdr_4addr *)skb->data; |
268 | skb->len < hdr_len) | 284 | |
269 | return -1; | 285 | if (skb_headroom(skb) < 8 || skb->len < hdr_len) |
286 | return NULL; | ||
270 | 287 | ||
271 | hdr = (struct ieee80211_hdr *)skb->data; | ||
272 | if (!tkey->tx_phase1_done) { | 288 | if (!tkey->tx_phase1_done) { |
273 | tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, | 289 | tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, |
274 | tkey->tx_iv32); | 290 | tkey->tx_iv32); |
275 | tkey->tx_phase1_done = 1; | 291 | tkey->tx_phase1_done = 1; |
276 | } | 292 | } |
293 | rc4key = kmalloc(16, GFP_ATOMIC); | ||
294 | if (!rc4key) | ||
295 | return NULL; | ||
277 | tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); | 296 | tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); |
278 | 297 | ||
279 | len = skb->len - hdr_len; | 298 | len = skb->len - hdr_len; |
@@ -282,9 +301,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
282 | pos += hdr_len; | 301 | pos += hdr_len; |
283 | icv = skb_put(skb, 4); | 302 | icv = skb_put(skb, 4); |
284 | 303 | ||
285 | *pos++ = rc4key[0]; | 304 | *pos++ = *rc4key; |
286 | *pos++ = rc4key[1]; | 305 | *pos++ = *(rc4key + 1); |
287 | *pos++ = rc4key[2]; | 306 | *pos++ = *(rc4key + 2); |
288 | *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ; | 307 | *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ; |
289 | *pos++ = tkey->tx_iv32 & 0xff; | 308 | *pos++ = tkey->tx_iv32 & 0xff; |
290 | *pos++ = (tkey->tx_iv32 >> 8) & 0xff; | 309 | *pos++ = (tkey->tx_iv32 >> 8) & 0xff; |
@@ -297,6 +316,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
297 | icv[2] = crc >> 16; | 316 | icv[2] = crc >> 16; |
298 | icv[3] = crc >> 24; | 317 | icv[3] = crc >> 24; |
299 | 318 | ||
319 | return rc4key; | ||
320 | } | ||
321 | |||
322 | static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | ||
323 | { | ||
324 | struct ieee80211_tkip_data *tkey = priv; | ||
325 | int len; | ||
326 | const u8 *rc4key; | ||
327 | u8 *pos; | ||
328 | struct scatterlist sg; | ||
329 | |||
330 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { | ||
331 | if (net_ratelimit()) { | ||
332 | struct ieee80211_hdr_4addr *hdr = | ||
333 | (struct ieee80211_hdr_4addr *)skb->data; | ||
334 | printk(KERN_DEBUG "TKIP countermeasures: dropped " | ||
335 | "TX packet to " MAC_FMT "\n", | ||
336 | MAC_ARG(hdr->addr1)); | ||
337 | } | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | if (skb_tailroom(skb) < 4 || skb->len < hdr_len) | ||
342 | return -1; | ||
343 | |||
344 | len = skb->len - hdr_len; | ||
345 | pos = skb->data + hdr_len; | ||
346 | |||
347 | rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv); | ||
348 | if (!rc4key) | ||
349 | return -1; | ||
350 | |||
300 | crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); | 351 | crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); |
301 | sg.page = virt_to_page(pos); | 352 | sg.page = virt_to_page(pos); |
302 | sg.offset = offset_in_page(pos); | 353 | sg.offset = offset_in_page(pos); |
@@ -319,16 +370,26 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
319 | u8 keyidx, *pos; | 370 | u8 keyidx, *pos; |
320 | u32 iv32; | 371 | u32 iv32; |
321 | u16 iv16; | 372 | u16 iv16; |
322 | struct ieee80211_hdr *hdr; | 373 | struct ieee80211_hdr_4addr *hdr; |
323 | u8 icv[4]; | 374 | u8 icv[4]; |
324 | u32 crc; | 375 | u32 crc; |
325 | struct scatterlist sg; | 376 | struct scatterlist sg; |
326 | int plen; | 377 | int plen; |
327 | 378 | ||
379 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | ||
380 | |||
381 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { | ||
382 | if (net_ratelimit()) { | ||
383 | printk(KERN_DEBUG "TKIP countermeasures: dropped " | ||
384 | "received packet from " MAC_FMT "\n", | ||
385 | MAC_ARG(hdr->addr2)); | ||
386 | } | ||
387 | return -1; | ||
388 | } | ||
389 | |||
328 | if (skb->len < hdr_len + 8 + 4) | 390 | if (skb->len < hdr_len + 8 + 4) |
329 | return -1; | 391 | return -1; |
330 | 392 | ||
331 | hdr = (struct ieee80211_hdr *)skb->data; | ||
332 | pos = skb->data + hdr_len; | 393 | pos = skb->data + hdr_len; |
333 | keyidx = pos[3]; | 394 | keyidx = pos[3]; |
334 | if (!(keyidx & (1 << 5))) { | 395 | if (!(keyidx & (1 << 5))) { |
@@ -441,9 +502,9 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, | |||
441 | 502 | ||
442 | static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) | 503 | static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) |
443 | { | 504 | { |
444 | struct ieee80211_hdr *hdr11; | 505 | struct ieee80211_hdr_4addr *hdr11; |
445 | 506 | ||
446 | hdr11 = (struct ieee80211_hdr *)skb->data; | 507 | hdr11 = (struct ieee80211_hdr_4addr *)skb->data; |
447 | switch (le16_to_cpu(hdr11->frame_ctl) & | 508 | switch (le16_to_cpu(hdr11->frame_ctl) & |
448 | (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { | 509 | (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { |
449 | case IEEE80211_FCTL_TODS: | 510 | case IEEE80211_FCTL_TODS: |
@@ -490,9 +551,9 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, | |||
490 | return 0; | 551 | return 0; |
491 | } | 552 | } |
492 | 553 | ||
493 | #if WIRELESS_EXT >= 18 | ||
494 | static void ieee80211_michael_mic_failure(struct net_device *dev, | 554 | static void ieee80211_michael_mic_failure(struct net_device *dev, |
495 | struct ieee80211_hdr *hdr, int keyidx) | 555 | struct ieee80211_hdr_4addr *hdr, |
556 | int keyidx) | ||
496 | { | 557 | { |
497 | union iwreq_data wrqu; | 558 | union iwreq_data wrqu; |
498 | struct iw_michaelmicfailure ev; | 559 | struct iw_michaelmicfailure ev; |
@@ -510,28 +571,6 @@ static void ieee80211_michael_mic_failure(struct net_device *dev, | |||
510 | wrqu.data.length = sizeof(ev); | 571 | wrqu.data.length = sizeof(ev); |
511 | wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); | 572 | wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); |
512 | } | 573 | } |
513 | #elif WIRELESS_EXT >= 15 | ||
514 | static void ieee80211_michael_mic_failure(struct net_device *dev, | ||
515 | struct ieee80211_hdr *hdr, int keyidx) | ||
516 | { | ||
517 | union iwreq_data wrqu; | ||
518 | char buf[128]; | ||
519 | |||
520 | /* TODO: needed parameters: count, keyid, key type, TSC */ | ||
521 | sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" | ||
522 | MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni", | ||
523 | MAC_ARG(hdr->addr2)); | ||
524 | memset(&wrqu, 0, sizeof(wrqu)); | ||
525 | wrqu.data.length = strlen(buf); | ||
526 | wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); | ||
527 | } | ||
528 | #else /* WIRELESS_EXT >= 15 */ | ||
529 | static inline void ieee80211_michael_mic_failure(struct net_device *dev, | ||
530 | struct ieee80211_hdr *hdr, | ||
531 | int keyidx) | ||
532 | { | ||
533 | } | ||
534 | #endif /* WIRELESS_EXT >= 15 */ | ||
535 | 574 | ||
536 | static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, | 575 | static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, |
537 | int hdr_len, void *priv) | 576 | int hdr_len, void *priv) |
@@ -547,8 +586,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, | |||
547 | skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) | 586 | skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) |
548 | return -1; | 587 | return -1; |
549 | if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { | 588 | if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { |
550 | struct ieee80211_hdr *hdr; | 589 | struct ieee80211_hdr_4addr *hdr; |
551 | hdr = (struct ieee80211_hdr *)skb->data; | 590 | hdr = (struct ieee80211_hdr_4addr *)skb->data; |
552 | printk(KERN_DEBUG "%s: Michael MIC verification failed for " | 591 | printk(KERN_DEBUG "%s: Michael MIC verification failed for " |
553 | "MSDU from " MAC_FMT " keyidx=%d\n", | 592 | "MSDU from " MAC_FMT " keyidx=%d\n", |
554 | skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2), | 593 | skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2), |
@@ -654,19 +693,22 @@ static char *ieee80211_tkip_print_stats(char *p, void *priv) | |||
654 | } | 693 | } |
655 | 694 | ||
656 | static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { | 695 | static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { |
657 | .name = "TKIP", | 696 | .name = "TKIP", |
658 | .init = ieee80211_tkip_init, | 697 | .init = ieee80211_tkip_init, |
659 | .deinit = ieee80211_tkip_deinit, | 698 | .deinit = ieee80211_tkip_deinit, |
660 | .encrypt_mpdu = ieee80211_tkip_encrypt, | 699 | .encrypt_mpdu = ieee80211_tkip_encrypt, |
661 | .decrypt_mpdu = ieee80211_tkip_decrypt, | 700 | .decrypt_mpdu = ieee80211_tkip_decrypt, |
662 | .encrypt_msdu = ieee80211_michael_mic_add, | 701 | .encrypt_msdu = ieee80211_michael_mic_add, |
663 | .decrypt_msdu = ieee80211_michael_mic_verify, | 702 | .decrypt_msdu = ieee80211_michael_mic_verify, |
664 | .set_key = ieee80211_tkip_set_key, | 703 | .set_key = ieee80211_tkip_set_key, |
665 | .get_key = ieee80211_tkip_get_key, | 704 | .get_key = ieee80211_tkip_get_key, |
666 | .print_stats = ieee80211_tkip_print_stats, | 705 | .print_stats = ieee80211_tkip_print_stats, |
667 | .extra_prefix_len = 4 + 4, /* IV + ExtIV */ | 706 | .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */ |
668 | .extra_postfix_len = 8 + 4, /* MIC + ICV */ | 707 | .extra_mpdu_postfix_len = 4, /* ICV */ |
669 | .owner = THIS_MODULE, | 708 | .extra_msdu_postfix_len = 8, /* MIC */ |
709 | .get_flags = ieee80211_tkip_get_flags, | ||
710 | .set_flags = ieee80211_tkip_set_flags, | ||
711 | .owner = THIS_MODULE, | ||
670 | }; | 712 | }; |
671 | 713 | ||
672 | static int __init ieee80211_crypto_tkip_init(void) | 714 | static int __init ieee80211_crypto_tkip_init(void) |