diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-05-01 01:45:26 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2011-05-01 01:45:26 +0000 |
commit | ebcc60cf355d1e0499a5e9d01a1058508946256e (patch) | |
tree | a4130bb5a46d694b13e031ff754e707e49aa259d /package/mac80211 | |
parent | 9c910833fbc592ace4c7b776097fbd4e2d094b4b (diff) | |
download | upstream-ebcc60cf355d1e0499a5e9d01a1058508946256e.tar.gz upstream-ebcc60cf355d1e0499a5e9d01a1058508946256e.tar.bz2 upstream-ebcc60cf355d1e0499a5e9d01a1058508946256e.zip |
mac80211: detect and drop incoming packets with invalid CCMP packet numbers to fix connection hangs on some devices
SVN-Revision: 26795
Diffstat (limited to 'package/mac80211')
-rw-r--r-- | package/mac80211/patches/420-mac80211_ignore_invalid_ccmp_rx_pn.patch | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/package/mac80211/patches/420-mac80211_ignore_invalid_ccmp_rx_pn.patch b/package/mac80211/patches/420-mac80211_ignore_invalid_ccmp_rx_pn.patch new file mode 100644 index 0000000000..4d0f861344 --- /dev/null +++ b/package/mac80211/patches/420-mac80211_ignore_invalid_ccmp_rx_pn.patch @@ -0,0 +1,46 @@ +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -86,6 +86,7 @@ struct ieee80211_key { + * Management frames. + */ + u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6]; ++ u8 rx_invalid_pn[NUM_RX_DATA_QUEUES + 1]; + struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCCMPReplays */ + /* scratch buffers for virt_to_page() (crypto API) */ +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -407,6 +407,13 @@ ieee80211_crypto_ccmp_encrypt(struct iee + return TX_CONTINUE; + } + ++static inline u64 pn_to_u64(u8 *data) ++{ ++ u64 pn = get_unaligned_be32(data + 2); ++ pn |= ((u64) get_unaligned_be16(data)) << 32; ++ return pn; ++} ++ + + ieee80211_rx_result + ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) +@@ -419,6 +426,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee + u8 pn[CCMP_PN_LEN]; + int data_len; + int queue; ++ u64 diff; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + +@@ -452,6 +460,11 @@ ieee80211_crypto_ccmp_decrypt(struct iee + return RX_DROP_UNUSABLE; + } + ++ diff = pn_to_u64(pn) - pn_to_u64(key->u.ccmp.rx_pn[queue]); ++ if (diff > 1000 && key->u.ccmp.rx_invalid_pn[queue]++ < 10) ++ return RX_DROP_UNUSABLE; ++ ++ key->u.ccmp.rx_invalid_pn[queue] = 0; + memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); + + /* Remove CCMP header and MIC */ |