aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_crypt_tkip.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-24 13:15:13 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-24 13:15:13 -0400
commita319a2773a13bab56a0d0b3744ba8703324313b5 (patch)
treef02c86acabd1031439fd422a167784007e84ebb1 /net/ieee80211/ieee80211_crypt_tkip.c
parente18fa700c9a31360bc8f193aa543b7ef7b39a06b (diff)
parent183798799216fad36c7219fe8d4d6dee6b8fa755 (diff)
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (217 commits) net/ieee80211: fix more crypto-related build breakage [PATCH] Spidernet: add ethtool -S (show statistics) [NET] GT96100: Delete bitrotting ethernet driver [PATCH] mv643xx_eth: restrict to 32-bit PPC_MULTIPLATFORM [PATCH] Cirrus Logic ep93xx ethernet driver r8169: the MMIO region of the 8167 stands behin BAR#1 e1000, ixgb: Remove pointless wrappers [PATCH] Remove powerpc specific parts of 3c509 driver [PATCH] s2io: Switch to pci_get_device [PATCH] gt96100: move to pci_get_device API [PATCH] ehea: bugfix for register access functions [PATCH] e1000 disable device on PCI error drivers/net/phy/fixed: #if 0 some incomplete code drivers/net: const-ify ethtool_ops declarations [PATCH] ethtool: allow const ethtool_ops [PATCH] sky2: big endian [PATCH] sky2: fiber support [PATCH] sky2: tx pause bug fix drivers/net: Trim trailing whitespace [PATCH] ehea: IBM eHEA Ethernet Device Driver ... Manually resolved conflicts in drivers/net/ixgb/ixgb_main.c and drivers/net/sky2.c related to CHECKSUM_HW/CHECKSUM_PARTIAL changes by commit 84fa7933a33f806bbbaae6775e87459b1ec584c0 that just happened to be next to unrelated changes in this update.
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_tkip.c')
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c114
1 files changed, 80 insertions, 34 deletions
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 407a17495b61..4200ec509866 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -53,8 +53,10 @@ struct ieee80211_tkip_data {
53 53
54 int key_idx; 54 int key_idx;
55 55
56 struct crypto_blkcipher *tfm_arc4; 56 struct crypto_blkcipher *rx_tfm_arc4;
57 struct crypto_hash *tfm_michael; 57 struct crypto_hash *rx_tfm_michael;
58 struct crypto_blkcipher *tx_tfm_arc4;
59 struct crypto_hash *tx_tfm_michael;
58 60
59 /* scratch buffers for virt_to_page() (crypto API) */ 61 /* scratch buffers for virt_to_page() (crypto API) */
60 u8 rx_hdr[16], tx_hdr[16]; 62 u8 rx_hdr[16], tx_hdr[16];
@@ -86,21 +88,39 @@ static void *ieee80211_tkip_init(int key_idx)
86 88
87 priv->key_idx = key_idx; 89 priv->key_idx = key_idx;
88 90
89 priv->tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, 91 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
90 CRYPTO_ALG_ASYNC); 92 CRYPTO_ALG_ASYNC);
91 if (IS_ERR(priv->tfm_arc4)) { 93 if (IS_ERR(priv->tx_tfm_arc4)) {
92 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 94 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
93 "crypto API arc4\n"); 95 "crypto API arc4\n");
94 priv->tfm_arc4 = NULL; 96 priv->tx_tfm_arc4 = NULL;
95 goto fail; 97 goto fail;
96 } 98 }
97 99
98 priv->tfm_michael = crypto_alloc_hash("michael_mic", 0, 100 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
99 CRYPTO_ALG_ASYNC); 101 CRYPTO_ALG_ASYNC);
100 if (IS_ERR(priv->tfm_michael)) { 102 if (IS_ERR(priv->tx_tfm_michael)) {
101 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 103 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
102 "crypto API michael_mic\n"); 104 "crypto API michael_mic\n");
103 priv->tfm_michael = NULL; 105 priv->tx_tfm_michael = NULL;
106 goto fail;
107 }
108
109 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
110 CRYPTO_ALG_ASYNC);
111 if (IS_ERR(priv->rx_tfm_arc4)) {
112 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
113 "crypto API arc4\n");
114 priv->rx_tfm_arc4 = NULL;
115 goto fail;
116 }
117
118 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
119 CRYPTO_ALG_ASYNC);
120 if (IS_ERR(priv->rx_tfm_michael)) {
121 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
122 "crypto API michael_mic\n");
123 priv->rx_tfm_michael = NULL;
104 goto fail; 124 goto fail;
105 } 125 }
106 126
@@ -108,10 +128,14 @@ static void *ieee80211_tkip_init(int key_idx)
108 128
109 fail: 129 fail:
110 if (priv) { 130 if (priv) {
111 if (priv->tfm_michael) 131 if (priv->tx_tfm_michael)
112 crypto_free_hash(priv->tfm_michael); 132 crypto_free_hash(priv->tx_tfm_michael);
113 if (priv->tfm_arc4) 133 if (priv->tx_tfm_arc4)
114 crypto_free_blkcipher(priv->tfm_arc4); 134 crypto_free_blkcipher(priv->tx_tfm_arc4);
135 if (priv->rx_tfm_michael)
136 crypto_free_hash(priv->rx_tfm_michael);
137 if (priv->rx_tfm_arc4)
138 crypto_free_blkcipher(priv->rx_tfm_arc4);
115 kfree(priv); 139 kfree(priv);
116 } 140 }
117 141
@@ -121,10 +145,16 @@ static void *ieee80211_tkip_init(int key_idx)
121static void ieee80211_tkip_deinit(void *priv) 145static void ieee80211_tkip_deinit(void *priv)
122{ 146{
123 struct ieee80211_tkip_data *_priv = priv; 147 struct ieee80211_tkip_data *_priv = priv;
124 if (_priv && _priv->tfm_michael) 148 if (_priv) {
125 crypto_free_hash(_priv->tfm_michael); 149 if (_priv->tx_tfm_michael)
126 if (_priv && _priv->tfm_arc4) 150 crypto_free_hash(_priv->tx_tfm_michael);
127 crypto_free_blkcipher(_priv->tfm_arc4); 151 if (_priv->tx_tfm_arc4)
152 crypto_free_blkcipher(_priv->tx_tfm_arc4);
153 if (_priv->rx_tfm_michael)
154 crypto_free_hash(_priv->rx_tfm_michael);
155 if (_priv->rx_tfm_arc4)
156 crypto_free_blkcipher(_priv->rx_tfm_arc4);
157 }
128 kfree(priv); 158 kfree(priv);
129} 159}
130 160
@@ -323,7 +353,7 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
323static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 353static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
324{ 354{
325 struct ieee80211_tkip_data *tkey = priv; 355 struct ieee80211_tkip_data *tkey = priv;
326 struct blkcipher_desc desc = { .tfm = tkey->tfm_arc4 }; 356 struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
327 int len; 357 int len;
328 u8 rc4key[16], *pos, *icv; 358 u8 rc4key[16], *pos, *icv;
329 u32 crc; 359 u32 crc;
@@ -357,17 +387,30 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
357 icv[2] = crc >> 16; 387 icv[2] = crc >> 16;
358 icv[3] = crc >> 24; 388 icv[3] = crc >> 24;
359 389
360 crypto_blkcipher_setkey(tkey->tfm_arc4, rc4key, 16); 390 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
361 sg.page = virt_to_page(pos); 391 sg.page = virt_to_page(pos);
362 sg.offset = offset_in_page(pos); 392 sg.offset = offset_in_page(pos);
363 sg.length = len + 4; 393 sg.length = len + 4;
364 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); 394 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
365} 395}
366 396
397/*
398 * deal with seq counter wrapping correctly.
399 * refer to timer_after() for jiffies wrapping handling
400 */
401static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
402 u32 iv32_o, u16 iv16_o)
403{
404 if ((s32)iv32_n - (s32)iv32_o < 0 ||
405 (iv32_n == iv32_o && iv16_n <= iv16_o))
406 return 1;
407 return 0;
408}
409
367static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 410static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
368{ 411{
369 struct ieee80211_tkip_data *tkey = priv; 412 struct ieee80211_tkip_data *tkey = priv;
370 struct blkcipher_desc desc = { .tfm = tkey->tfm_arc4 }; 413 struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
371 u8 rc4key[16]; 414 u8 rc4key[16];
372 u8 keyidx, *pos; 415 u8 keyidx, *pos;
373 u32 iv32; 416 u32 iv32;
@@ -419,8 +462,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
419 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); 462 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
420 pos += 8; 463 pos += 8;
421 464
422 if (iv32 < tkey->rx_iv32 || 465 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
423 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
424 if (net_ratelimit()) { 466 if (net_ratelimit()) {
425 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT 467 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
426 " previous TSC %08x%04x received TSC " 468 " previous TSC %08x%04x received TSC "
@@ -439,7 +481,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
439 481
440 plen = skb->len - hdr_len - 12; 482 plen = skb->len - hdr_len - 12;
441 483
442 crypto_blkcipher_setkey(tkey->tfm_arc4, rc4key, 16); 484 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
443 sg.page = virt_to_page(pos); 485 sg.page = virt_to_page(pos);
444 sg.offset = offset_in_page(pos); 486 sg.offset = offset_in_page(pos);
445 sg.length = plen + 4; 487 sg.length = plen + 4;
@@ -484,13 +526,13 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
484 return keyidx; 526 return keyidx;
485} 527}
486 528
487static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, 529static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
488 u8 * data, size_t data_len, u8 * mic) 530 u8 * data, size_t data_len, u8 * mic)
489{ 531{
490 struct hash_desc desc; 532 struct hash_desc desc;
491 struct scatterlist sg[2]; 533 struct scatterlist sg[2];
492 534
493 if (tkey->tfm_michael == NULL) { 535 if (tfm_michael == NULL) {
494 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); 536 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
495 return -1; 537 return -1;
496 } 538 }
@@ -502,10 +544,10 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
502 sg[1].offset = offset_in_page(data); 544 sg[1].offset = offset_in_page(data);
503 sg[1].length = data_len; 545 sg[1].length = data_len;
504 546
505 if (crypto_hash_setkey(tkey->tfm_michael, key, 8)) 547 if (crypto_hash_setkey(tfm_michael, key, 8))
506 return -1; 548 return -1;
507 549
508 desc.tfm = tkey->tfm_michael; 550 desc.tfm = tfm_michael;
509 desc.flags = 0; 551 desc.flags = 0;
510 return crypto_hash_digest(&desc, sg, data_len + 16, mic); 552 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
511} 553}
@@ -541,7 +583,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
541 if (stype & IEEE80211_STYPE_QOS_DATA) { 583 if (stype & IEEE80211_STYPE_QOS_DATA) {
542 const struct ieee80211_hdr_3addrqos *qoshdr = 584 const struct ieee80211_hdr_3addrqos *qoshdr =
543 (struct ieee80211_hdr_3addrqos *)skb->data; 585 (struct ieee80211_hdr_3addrqos *)skb->data;
544 hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; 586 hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
545 } else 587 } else
546 hdr[12] = 0; /* priority */ 588 hdr[12] = 0; /* priority */
547 589
@@ -563,7 +605,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
563 605
564 michael_mic_hdr(skb, tkey->tx_hdr); 606 michael_mic_hdr(skb, tkey->tx_hdr);
565 pos = skb_put(skb, 8); 607 pos = skb_put(skb, 8);
566 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr, 608 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
567 skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) 609 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
568 return -1; 610 return -1;
569 611
@@ -601,7 +643,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
601 return -1; 643 return -1;
602 644
603 michael_mic_hdr(skb, tkey->rx_hdr); 645 michael_mic_hdr(skb, tkey->rx_hdr);
604 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr, 646 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
605 skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) 647 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
606 return -1; 648 return -1;
607 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { 649 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
@@ -631,14 +673,18 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
631{ 673{
632 struct ieee80211_tkip_data *tkey = priv; 674 struct ieee80211_tkip_data *tkey = priv;
633 int keyidx; 675 int keyidx;
634 struct crypto_hash *tfm = tkey->tfm_michael; 676 struct crypto_hash *tfm = tkey->tx_tfm_michael;
635 struct crypto_blkcipher *tfm2 = tkey->tfm_arc4; 677 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
678 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
679 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
636 680
637 keyidx = tkey->key_idx; 681 keyidx = tkey->key_idx;
638 memset(tkey, 0, sizeof(*tkey)); 682 memset(tkey, 0, sizeof(*tkey));
639 tkey->key_idx = keyidx; 683 tkey->key_idx = keyidx;
640 tkey->tfm_michael = tfm; 684 tkey->tx_tfm_michael = tfm;
641 tkey->tfm_arc4 = tfm2; 685 tkey->tx_tfm_arc4 = tfm2;
686 tkey->rx_tfm_michael = tfm3;
687 tkey->rx_tfm_arc4 = tfm4;
642 if (len == TKIP_KEY_LEN) { 688 if (len == TKIP_KEY_LEN) {
643 memcpy(tkey->key, key, TKIP_KEY_LEN); 689 memcpy(tkey->key, key, TKIP_KEY_LEN);
644 tkey->key_set = 1; 690 tkey->key_set = 1;