d80211: fix wep_tfm race
Subsystems (2)
PATCH 2/2 d80211: fix wep_tfm race
The TX/RX path all use the local->wep_tfm to encrypt and decrypt packets. Each {en|de}crypt operation need set a new RC4key, this may corrupt the previous set key that is still being used. Thus cause a lot of decrypton error or encryption with the wrong key. Use two tfm (tx_tfm and rx_tfm) to avoid this race.
Signed-off-by Hong Liu <[email protected]>
---
net/d80211/ieee80211_i.h | 3 ++- net/d80211/wep.c | 18 +++++++++++++----- net/d80211/wpa.c | 6 ++++-- 3 files changed, 19 insertions(+), 8 deletions(-)
634c9615ce3cd06dc7f6aff05e43e61490a53472
net/d80211/ieee80211_i.h +2 -1
@@ -402,7 +402,8 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12int long_retry_limit;/* dot11LongRetryLimit */ int short_preamble;/* use short preamble with IEEE 802.11b */ -struct crypto_tfm *wep_tfm; +struct crypto_tfm *wep_tx_tfm; +struct crypto_tfm *wep_rx_tfm;u32 wep_iv;int key_tx_rx_threshold;/* number of times any key can be used in TX * or RX before generating a rekey
net/d80211/wep.c +13 -5
@@ -26,16 +26,23 @@ int ieee80211_wep_init(struct ieee80211_/* start WEP IV from a random value */ get_random_bytes (&local->wep_iv,WEP_IV_LEN ); - local->wep_tfm =crypto_alloc_tfm ("arc4" ,0 ); -if (!local->wep_tfm) + local->wep_tx_tfm =crypto_alloc_tfm ("arc4" ,0 ); +if (!local->wep_tx_tfm)return -ENOMEM ; + local->wep_rx_tfm =crypto_alloc_tfm ("arc4" ,0 ); +if (!local->wep_rx_tfm) { +crypto_free_tfm (local->wep_tx_tfm); +return -ENOMEM ; + } +return 0 ; }void ieee80211_wep_free (struct ieee80211_local *local) { -crypto_free_tfm (local->wep_tfm); +crypto_free_tfm (local->wep_tx_tfm); +crypto_free_tfm (local->wep_rx_tfm); }static inline int ieee80211_wep_weak_iv (u32 iv,int keylen)
@@ -172,7 +179,8 @@ int ieee80211_wep_encrypt(struct ieee802/* Add room for ICV */ skb_put (skb,WEP_ICV_LEN ); -ieee80211_wep_encrypt_data (local->wep_tfm, rc4key, klen, iv +WEP_IV_LEN , len); +ieee80211_wep_encrypt_data (local->wep_tx_tfm, rc4key, klen, + iv +WEP_IV_LEN , len);kfree (rc4key);
@@ -252,7 +260,7 @@ int ieee80211_wep_decrypt(struct ieee802/* Copy rest of the WEP key (the secret part) */ memcpy (rc4key +3 , key->key, key->keylen); -if (ieee80211_wep_decrypt_data (local->wep_tfm, rc4key, klen, +if (ieee80211_wep_decrypt_data (local->wep_rx_tfm, rc4key, klen, skb->data + hdrlen +WEP_IV_LEN , len)) {printk (KERN_DEBUG "WEP decrypt failed (ICV)\n" );
net/d80211/wpa.c +4 -2
@@ -352,7 +352,8 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */skb_put (skb,TKIP_ICV_LEN ); hdr = (struct ieee80211_hdr *) skb->data; -ieee80211_tkip_encrypt_data (tx->local->wep_tfm, key, pos, len, hdr->addr2); +ieee80211_tkip_encrypt_data (tx->local->wep_tx_tfm, + key, pos, len, hdr->addr2);return 0 ; }
@@ -495,7 +496,8 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */ hwaccel =1 ; } - res =ieee80211_tkip_decrypt_data (rx->local->wep_tfm, key, skb->data + hdrlen, + res =ieee80211_tkip_decrypt_data (rx->local->wep_rx_tfm, + key, skb->data + hdrlen, skb->len - hdrlen, rx->sta->addr, hwaccel, rx->u.rx.queue);if (res !=TKIP_DECRYPT_OK || wpa_test) {
Signature · 1 line
1.3.3