1 --- a/net/mac80211/key.h
2 +++ b/net/mac80211/key.h
3 @@ -86,6 +86,7 @@ struct ieee80211_key {
6 u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6];
7 + u8 rx_invalid_pn[NUM_RX_DATA_QUEUES + 1];
8 struct crypto_cipher *tfm;
9 u32 replays; /* dot11RSNAStatsCCMPReplays */
10 /* scratch buffers for virt_to_page() (crypto API) */
11 --- a/net/mac80211/wpa.c
12 +++ b/net/mac80211/wpa.c
13 @@ -407,6 +407,13 @@ ieee80211_crypto_ccmp_encrypt(struct iee
17 +static inline u64 pn_to_u64(u8 *data)
19 + u64 pn = get_unaligned_be32(data + 2);
20 + pn |= ((u64) get_unaligned_be16(data)) << 32;
26 ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
27 @@ -419,6 +426,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
33 hdrlen = ieee80211_hdrlen(hdr->frame_control);
35 @@ -452,6 +460,11 @@ ieee80211_crypto_ccmp_decrypt(struct iee
36 return RX_DROP_UNUSABLE;
39 + diff = pn_to_u64(pn) - pn_to_u64(key->u.ccmp.rx_pn[queue]);
40 + if (diff > 1000 && key->u.ccmp.rx_invalid_pn[queue]++ < 10)
41 + return RX_DROP_UNUSABLE;
43 + key->u.ccmp.rx_invalid_pn[queue] = 0;
44 memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
46 /* Remove CCMP header and MIC */