diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/tkip.c | 16 | ||||
-rw-r--r-- | net/mac80211/tkip.h | 3 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 8 |
4 files changed, 21 insertions, 8 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 636de70cd85..32d19bbf522 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -153,6 +153,8 @@ struct ieee80211_txrx_data { int sent_ps_buffered; int queue; int load; + u32 tkip_iv32; + u16 tkip_iv16; } rx; } u; }; diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 5b11f14abfb..3abe194e4d5 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -238,7 +238,8 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, - int only_iv, int queue) + int only_iv, int queue, + u32 *out_iv32, u16 *out_iv16) { u32 iv32; u32 iv16; @@ -332,11 +333,14 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); done: if (res == TKIP_DECRYPT_OK) { - /* FIX: these should be updated only after Michael MIC has been - * verified */ - /* Record previously received IV */ - key->u.tkip.iv32_rx[queue] = iv32; - key->u.tkip.iv16_rx[queue] = iv16; + /* + * Record previously received IV, will be copied into the + * key information after MIC verification. It is possible + * that we don't catch replays of fragments but that's ok + * because the Michael MIC verication will then fail. + */ + *out_iv32 = iv32; + *out_iv16 = iv16; } return res; diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index a0d181a1804..73d8ef2a93b 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h @@ -31,6 +31,7 @@ enum { int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, - int only_iv, int queue); + int only_iv, int queue, + u32 *out_iv32, u16 *out_iv16); #endif /* TKIP_H */ diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index a07fd7484cd..6695efba57e 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -175,6 +175,10 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx) /* remove Michael MIC from payload */ skb_trim(skb, skb->len - MICHAEL_MIC_LEN); + /* update IV in key information to be able to detect replays */ + rx->key->u.tkip.iv32_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv32; + rx->key->u.tkip.iv16_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv16; + return TXRX_CONTINUE; } @@ -315,7 +319,9 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx) 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); + hwaccel, rx->u.rx.queue, + &rx->u.rx.tkip_iv32, + &rx->u.rx.tkip_iv16); if (res != TKIP_DECRYPT_OK || wpa_test) { printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from " "%s (res=%d)\n", |