mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
mac80211: assure all fragments are encrypted
Do not mix plaintext and encrypted fragments in protected Wi-Fi networks. This fixes CVE-2020-26147. Previously, an attacker was able to first forward a legitimate encrypted fragment towards a victim, followed by a plaintext fragment. The encrypted and plaintext fragment would then be reassembled. For further details see Section 6.3 and Appendix D in the paper "Fragment and Forge: Breaking Wi-Fi Through Frame Aggregation and Fragmentation". Because of this change there are now two equivalent conditions in the code to determine if a received fragment requires sequential PNs, so we also move this test to a separate function to make the code easier to maintain. Cc: stable@vger.kernel.org Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be> Link: https://lore.kernel.org/r/20210511200110.30c4394bb835.I5acfdb552cc1d20c339c262315950b3eac491397@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
297c4de6f7
commit
965a7d72e7
1 changed files with 12 additions and 11 deletions
|
@ -2194,6 +2194,16 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc)
|
||||
{
|
||||
return rx->key &&
|
||||
(rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
|
||||
ieee80211_has_protected(fc);
|
||||
}
|
||||
|
||||
static ieee80211_rx_result debug_noinline
|
||||
ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
|
@ -2238,12 +2248,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
/* This is the first fragment of a new frame. */
|
||||
entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
|
||||
rx->seqno_idx, &(rx->skb));
|
||||
if (rx->key &&
|
||||
(rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
|
||||
ieee80211_has_protected(fc)) {
|
||||
if (requires_sequential_pn(rx, fc)) {
|
||||
int queue = rx->security_idx;
|
||||
|
||||
/* Store CCMP/GCMP PN so that we can verify that the
|
||||
|
@ -2285,11 +2290,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
|
||||
int queue;
|
||||
|
||||
if (!rx->key ||
|
||||
(rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
|
||||
rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
|
||||
rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
|
||||
rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
|
||||
if (!requires_sequential_pn(rx, fc))
|
||||
return RX_DROP_UNUSABLE;
|
||||
memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
|
||||
for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
|
||||
|
|
Loading…
Reference in a new issue