Commit 34459512 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: fix TKIP replay vulnerability

Unlike CCMP, the presence or absence of the QoS
field doesn't change the encryption, only the
TID is used. When no QoS field is present, zero
is used as the TID value. This means that it is
possible for an attacker to take a QoS packet
with TID 0 and replay it as a non-QoS packet.

Unfortunately, mac80211 uses different IVs for
checking the validity of the packet's TKIP IV
when it checks TID 0 and when it checks non-QoS
packets. This means it is vulnerable to this
replay attack.

To fix this, use the same replay counter for
TID 0 and non-QoS packets by overriding the
rx->queue value to 0 if it is 16 (non-QoS).

This is a minimal fix for now. I caused this
issue in

commit 1411f9b5
Author: Johannes Berg <johannes@sipsolutions.net>
Date:   Thu Jul 10 10:11:02 2008 +0200

    mac80211: fix RX sequence number check

while fixing a sequence number issue (there,
a separate counter needs to be used).

Cc: stable@kernel.org
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1186980d
...@@ -86,6 +86,11 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) ...@@ -86,6 +86,11 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
struct sk_buff *skb = rx->skb; struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
int queue = rx->queue;
/* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
if (rx->queue == NUM_RX_DATA_QUEUES - 1)
queue = 0;
/* /*
* it makes no sense to check for MIC errors on anything other * it makes no sense to check for MIC errors on anything other
...@@ -148,8 +153,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) ...@@ -148,8 +153,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
update_iv: update_iv:
/* update IV in key information to be able to detect replays */ /* update IV in key information to be able to detect replays */
rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32;
rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16;
return RX_CONTINUE; return RX_CONTINUE;
...@@ -241,6 +246,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) ...@@ -241,6 +246,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
struct ieee80211_key *key = rx->key; struct ieee80211_key *key = rx->key;
struct sk_buff *skb = rx->skb; struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
int queue = rx->queue;
/* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
if (rx->queue == NUM_RX_DATA_QUEUES - 1)
queue = 0;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
...@@ -261,7 +271,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) ...@@ -261,7 +271,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
key, skb->data + hdrlen, key, skb->data + hdrlen,
skb->len - hdrlen, rx->sta->sta.addr, skb->len - hdrlen, rx->sta->sta.addr,
hdr->addr1, hwaccel, rx->queue, hdr->addr1, hwaccel, queue,
&rx->tkip_iv32, &rx->tkip_iv32,
&rx->tkip_iv16); &rx->tkip_iv16);
if (res != TKIP_DECRYPT_OK) if (res != TKIP_DECRYPT_OK)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment