aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_crypt_wep.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2006-08-20 23:33:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-08-29 17:06:30 -0400
commit5a656949719bf8598ad1e93a56eb11e70a4c3208 (patch)
treeea0df5c37e264903b9e82e4ec7ade946e6d39be2 /net/ieee80211/ieee80211_crypt_wep.c
parentb4328d87ec5711543b818fea2e1cf64f09d326f1 (diff)
[PATCH] ieee80211: Fix TKIP and WEP decryption error on SMP machines
The IEEE80211 TKIP and WEP Tx and Rx paths use the same crypto_tfm to encrypt and decrypt data. During the encrypt and decrypt process, both of them will set a new key to crypto_tfm. If they happen on the same time, it will corrupt the crypto_tfm. Thus users will receive an ICV error or Michael MIC error. This only likely to happen on SMP box with heavy traffic both on Tx and Rx. The patch use two sets of crypto_tfms to avoid this problem. Signed-off-by: Hong Liu <hong.liu@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_wep.c')
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 0ebf235f6939..b435b28857ed 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -32,7 +32,8 @@ struct prism2_wep_data {
32 u8 key[WEP_KEY_LEN + 1]; 32 u8 key[WEP_KEY_LEN + 1];
33 u8 key_len; 33 u8 key_len;
34 u8 key_idx; 34 u8 key_idx;
35 struct crypto_tfm *tfm; 35 struct crypto_tfm *tx_tfm;
36 struct crypto_tfm *rx_tfm;
36}; 37};
37 38
38static void *prism2_wep_init(int keyidx) 39static void *prism2_wep_init(int keyidx)
@@ -44,13 +45,19 @@ static void *prism2_wep_init(int keyidx)
44 goto fail; 45 goto fail;
45 priv->key_idx = keyidx; 46 priv->key_idx = keyidx;
46 47
47 priv->tfm = crypto_alloc_tfm("arc4", 0); 48 priv->tx_tfm = crypto_alloc_tfm("arc4", 0);
48 if (priv->tfm == NULL) { 49 if (priv->tx_tfm == NULL) {
49 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " 50 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
50 "crypto API arc4\n"); 51 "crypto API arc4\n");
51 goto fail; 52 goto fail;
52 } 53 }
53 54
55 priv->rx_tfm = crypto_alloc_tfm("arc4", 0);
56 if (priv->rx_tfm == NULL) {
57 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
58 "crypto API arc4\n");
59 goto fail;
60 }
54 /* start WEP IV from a random value */ 61 /* start WEP IV from a random value */
55 get_random_bytes(&priv->iv, 4); 62 get_random_bytes(&priv->iv, 4);
56 63
@@ -58,8 +65,10 @@ static void *prism2_wep_init(int keyidx)
58 65
59 fail: 66 fail:
60 if (priv) { 67 if (priv) {
61 if (priv->tfm) 68 if (priv->tx_tfm)
62 crypto_free_tfm(priv->tfm); 69 crypto_free_tfm(priv->tx_tfm);
70 if (priv->rx_tfm)
71 crypto_free_tfm(priv->rx_tfm);
63 kfree(priv); 72 kfree(priv);
64 } 73 }
65 return NULL; 74 return NULL;
@@ -68,8 +77,12 @@ static void *prism2_wep_init(int keyidx)
68static void prism2_wep_deinit(void *priv) 77static void prism2_wep_deinit(void *priv)
69{ 78{
70 struct prism2_wep_data *_priv = priv; 79 struct prism2_wep_data *_priv = priv;
71 if (_priv && _priv->tfm) 80 if (_priv) {
72 crypto_free_tfm(_priv->tfm); 81 if (_priv->tx_tfm)
82 crypto_free_tfm(_priv->tx_tfm);
83 if (_priv->rx_tfm)
84 crypto_free_tfm(_priv->rx_tfm);
85 }
73 kfree(priv); 86 kfree(priv);
74} 87}
75 88
@@ -151,11 +164,11 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
151 icv[2] = crc >> 16; 164 icv[2] = crc >> 16;
152 icv[3] = crc >> 24; 165 icv[3] = crc >> 24;
153 166
154 crypto_cipher_setkey(wep->tfm, key, klen); 167 crypto_cipher_setkey(wep->tx_tfm, key, klen);
155 sg.page = virt_to_page(pos); 168 sg.page = virt_to_page(pos);
156 sg.offset = offset_in_page(pos); 169 sg.offset = offset_in_page(pos);
157 sg.length = len + 4; 170 sg.length = len + 4;
158 crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4); 171 crypto_cipher_encrypt(wep->tx_tfm, &sg, &sg, len + 4);
159 172
160 return 0; 173 return 0;
161} 174}
@@ -194,11 +207,11 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
194 /* Apply RC4 to data and compute CRC32 over decrypted data */ 207 /* Apply RC4 to data and compute CRC32 over decrypted data */
195 plen = skb->len - hdr_len - 8; 208 plen = skb->len - hdr_len - 8;
196 209
197 crypto_cipher_setkey(wep->tfm, key, klen); 210 crypto_cipher_setkey(wep->rx_tfm, key, klen);
198 sg.page = virt_to_page(pos); 211 sg.page = virt_to_page(pos);
199 sg.offset = offset_in_page(pos); 212 sg.offset = offset_in_page(pos);
200 sg.length = plen + 4; 213 sg.length = plen + 4;
201 crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4); 214 crypto_cipher_decrypt(wep->rx_tfm, &sg, &sg, plen + 4);
202 215
203 crc = ~crc32_le(~0, pos, plen); 216 crc = ~crc32_le(~0, pos, plen);
204 icv[0] = crc; 217 icv[0] = crc;