Skip to contentSkip to conversation

Patch "mac80211: check PN correctly for GCMP-encrypted fragmented MPDUs" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Mar 12, 2016

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

mac80211: check PN correctly for GCMP-encrypted fragmented MPDUs

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
mac80211-check-pn-correctly-for-gcmp-encrypted-fragmented-mpdus.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 9acc54beb474c81148e2946603d141cf8716b19f Mon Sep 17 00:00:00 2001

From: Johannes Berg <[email protected]>
Date: Fri, 26 Feb 2016 22:13:40 +0100
Subject: mac80211: check PN correctly for GCMP-encrypted fragmented MPDUs

From: Johannes Berg <[email protected]>

commit 9acc54beb474c81148e2946603d141cf8716b19f upstream.

Just like for CCMP we need to check that for GCMP the fragments have PNs that increment by one; the spec was updated to fix this security issue and now has the following text:

The receiver shall discard MSDUs and MMPDUs whose constituent MPDU PN values are not incrementing in steps of 1.

Adapt the code for CCMP to work for GCMP as well, luckily the relevant fields already alias each other so no code duplication is needed (just check the aliasing with BUILD_BUG_ON.)

---
 net/mac80211/ieee80211_i.h |    2 +-
 net/mac80211/rx.c          |   36 +++++++++++++++++++++++++++---------
 2 files changed, 28 insertions(+), 10 deletions(-)
net/mac80211/ieee80211_i.h +1 -1
@@ -92,7 +92,7 @@ struct ieee80211_fragment_entry {
 	u16 extra_len;
 	u16 last_frag;
 	u8 rx_queue;
-	bool ccmp; /* Whether fragments were encrypted with CCMP */
+	bool check_sequential_pn; /* needed for CCMP/GCMP */
 	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
 };
 
net/mac80211/rx.c +27 -9
@@ -1754,7 +1754,7 @@ ieee80211_reassemble_add(struct ieee8021
 	entry->seq = seq;
 	entry->rx_queue = rx_queue;
 	entry->last_frag = frag;
-	entry->ccmp = 0;
+	entry->check_sequential_pn = false;
 	entry->extra_len = 0;
 
 	return entry;
@@ -1850,15 +1850,27 @@ ieee80211_rx_h_defragment(struct ieee802
 						 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_CCMP_256 ||
+		     rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
+		     rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
 		    ieee80211_has_protected(fc)) {
 			int queue = rx->security_idx;
-			/* Store CCMP PN so that we can verify that the next
-			 * fragment has a sequential PN value. */
-			entry->ccmp = 1;
+
+			/* Store CCMP/GCMP PN so that we can verify that the
+			 * next fragment has a sequential PN value.
+			 */
+			entry->check_sequential_pn = true;
 			memcpy(entry->last_pn,
 			       rx->key->u.ccmp.rx_pn[queue],
 			       IEEE80211_CCMP_PN_LEN);
+			BUILD_BUG_ON(offsetof(struct ieee80211_key,
+					      u.ccmp.rx_pn) !=
+				     offsetof(struct ieee80211_key,
+					      u.gcmp.rx_pn));
+			BUILD_BUG_ON(sizeof(rx->key->u.ccmp.rx_pn[queue]) !=
+				     sizeof(rx->key->u.gcmp.rx_pn[queue]));
+			BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
+				     IEEE80211_GCMP_PN_LEN);
 		}
 		return RX_QUEUED;
 	}
@@ -1873,15 +1885,21 @@ ieee80211_rx_h_defragment(struct ieee802
 		return RX_DROP_MONITOR;
 	}
 
-	/* Verify that MPDUs within one MSDU have sequential PN values.
-	 * (IEEE 802.11i, 8.3.3.4.5) */
-	if (entry->ccmp) {
+	/* "The receiver shall discard MSDUs and MMPDUs whose constituent
+	 *  MPDU PN values are not incrementing in steps of 1."
+	 * see IEEE P802.11-REVmc/D5.0, 12.5.3.4.4, item d (for CCMP)
+	 * and IEEE P802.11-REVmc/D5.0, 12.5.5.4.4, item d (for GCMP)
+	 */
+	if (entry->check_sequential_pn) {
 		int i;
 		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_CCMP_256 &&
+		     rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
+		     rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
 			return RX_DROP_UNUSABLE;
 		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
 		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/mac80211-check-pn-correctly-for-gcmp-encrypted-fragmented-mpdus.patch queue-4.4/cfg80211-wext-fix-message-ordering.patch queue-4.4/mac80211-minstrel_ht-set-default-tx-aggregation-timeout-to-0.patch queue-4.4/mac80211-fix-public-action-frame-rx-in-ap-mode.patch queue-4.4/wext-fix-message-delay-ordering.patch queue-4.4/mac80211-minstrel-change-expected-throughput-unit-back-to-kbps.patch queue-4.4/mac80211-minstrel_ht-fix-a-logic-error-in-rts-cts-handling.patch queue-4.4/mac80211-fix-use-of-uninitialised-values-in-rx-aggregation.patch