All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit f631a77b authored by Sara Sharon's avatar Sara Sharon Committed by Johannes Berg

mac80211: allow same PN for AMSDU sub-frames

Some hardware (iwlwifi an example) de-aggregate AMSDUs and copy the IV
as is to the generated MPDUs, so the same PN appears in multiple
packets without being a replay attack.  Allow driver to explicitly
indicate that a frame is allowed to have the same PN as the previous
frame.
Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 20eb7ea9
...@@ -1068,6 +1068,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -1068,6 +1068,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific * @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific
* radiotap data in the skb->data (before the frame) as described by * radiotap data in the skb->data (before the frame) as described by
* the &struct ieee80211_vendor_radiotap. * the &struct ieee80211_vendor_radiotap.
* @RX_FLAG_ALLOW_SAME_PN: Allow the same PN as same packet before.
* This is used for AMSDU subframes which can have the same PN as
* the first subframe.
*/ */
enum mac80211_rx_flags { enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0), RX_FLAG_MMIC_ERROR = BIT(0),
...@@ -1102,6 +1105,7 @@ enum mac80211_rx_flags { ...@@ -1102,6 +1105,7 @@ enum mac80211_rx_flags {
RX_FLAG_AMSDU_MORE = BIT(30), RX_FLAG_AMSDU_MORE = BIT(30),
RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31), RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31),
RX_FLAG_MIC_STRIPPED = BIT_ULL(32), RX_FLAG_MIC_STRIPPED = BIT_ULL(32),
RX_FLAG_ALLOW_SAME_PN = BIT_ULL(33),
}; };
#define RX_FLAG_STBC_SHIFT 26 #define RX_FLAG_STBC_SHIFT 26
......
...@@ -519,12 +519,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, ...@@ -519,12 +519,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (!(status->flag & RX_FLAG_PN_VALIDATED)) { if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
int res;
ccmp_hdr2pn(pn, skb->data + hdrlen); ccmp_hdr2pn(pn, skb->data + hdrlen);
queue = rx->security_idx; queue = rx->security_idx;
if (memcmp(pn, key->u.ccmp.rx_pn[queue], res = memcmp(pn, key->u.ccmp.rx_pn[queue],
IEEE80211_CCMP_PN_LEN) <= 0) { IEEE80211_CCMP_PN_LEN);
if (res < 0 ||
(!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) {
key->u.ccmp.replays++; key->u.ccmp.replays++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
...@@ -745,12 +749,16 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -745,12 +749,16 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (!(status->flag & RX_FLAG_PN_VALIDATED)) { if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
int res;
gcmp_hdr2pn(pn, skb->data + hdrlen); gcmp_hdr2pn(pn, skb->data + hdrlen);
queue = rx->security_idx; queue = rx->security_idx;
if (memcmp(pn, key->u.gcmp.rx_pn[queue], res = memcmp(pn, key->u.gcmp.rx_pn[queue],
IEEE80211_GCMP_PN_LEN) <= 0) { IEEE80211_GCMP_PN_LEN);
if (res < 0 ||
(!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) {
key->u.gcmp.replays++; key->u.gcmp.replays++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
......
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