Skip to contentSkip to conversation

mac80211: Add an RX flag to skip Michael MIC verification

RFC In review Jouni Malinen 2 participants 2 messages Dec 18, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC 1/1 mac80211: Add an RX flag to skip Michael MIC verification

mac80211 used to allow drivers to indicate that Michael MIC has already been verified in received frames to allow the somewhat heavy operation of validating this in software to be avoided. This disappeared as part of hardware crypto flag rework (commit 7848ba7d7a010ccb265617fc2bc053e2bdf06f48). The changes below propose a bit different mechanism for achieving the same benefit for host CPU with wlan designs that can verify Michael MIC for unfragmented frames in hardware.

I'm also including a patch to ath9k to start using this new mechanism and move Michael MIC processing to hardware for both TX and RX whenever possible. It seems to work based on minimal testing, but I do not want to submit it to be merged before more thorough testing has taken place.

Some hardware acceleration designs for TKIP take care of Michael MIC verification in received frames (well, at least for frames that were not fragmented). Add an RX status flag to allow the expensive software validation of the Michael MIC to be skipped in cases where it has already been verified in hardware.

---
 include/net/mac80211.h |    3 +++
 net/mac80211/wpa.c     |    4 ++++
 2 files changed, 7 insertions(+)
include/net/mac80211.h +3 -0
@@ -439,6 +439,8 @@ ieee80211_tx_info_clear_status(struct ie
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
  * @RX_FLAG_SHORT_GI: Short guard interval was used
+ * @RX_FLAG_MMIC_VERIFIED: the hardware has verified the Michael MIC, but the
+ *	MIC has not been stripped off this frame.
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR	= 1<<0,
@@ -453,6 +455,7 @@ enum mac80211_rx_flags {
 	RX_FLAG_HT		= 1<<9,
 	RX_FLAG_40MHZ		= 1<<10,
 	RX_FLAG_SHORT_GI	= 1<<11,
+	RX_FLAG_MMIC_VERIFIED	= 1<<12,
 };
 
 /**
net/mac80211/wpa.c +4 -0
@@ -99,6 +99,9 @@ ieee80211_rx_h_michael_mic_verify(struct
 	    !ieee80211_is_data_present(hdr->frame_control))
 		return RX_CONTINUE;
 
+	if (rx->status->flag & RX_FLAG_MMIC_VERIFIED)
+		goto remove_mic;
+
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 	if (skb->len < hdrlen + MICHAEL_MIC_LEN)
 		return RX_DROP_UNUSABLE;
@@ -125,6 +128,7 @@ ieee80211_rx_h_michael_mic_verify(struct
 		return RX_DROP_UNUSABLE;
 	}
 
+remove_mic:
 	/* remove Michael MIC from payload */
 	skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
 

ath9k: Michael MIC in hardware

Remove request for mac80211 to calculate Michael MIC when TKIP is used since that is not needed with any hardware revisions supported by ath9k. Only fragmented frames need Michael MIC processing in the stack and that will be taken care of automatically without driver request. Mark received frames that that hardware decrypted to have passed Michael MIC verification if they were not fragmented (fragmented frames will continue to be verified in mac80211).

---
 drivers/net/wireless/ath9k/main.c |    3 ---
 drivers/net/wireless/ath9k/recv.c |   11 +++++++++++
 drivers/net/wireless/ath9k/xmit.c |    8 ++++++++
 3 files changed, 19 insertions(+), 3 deletions(-)
drivers/net/wireless/ath9k/main.c +0 -3
@@ -2366,10 +2366,7 @@ static int ath9k_set_key(struct ieee8021
 		ret = ath_key_config(sc, addr, key);
 		if (ret >= 0) {
 			key->hw_key_idx = ret;
-			/* push IV and Michael MIC generation to stack */
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-			if (key->alg == ALG_TKIP)
-				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
 			ret = 0;
 		}
 		break;
drivers/net/wireless/ath9k/recv.c +11 -0
@@ -594,6 +594,17 @@ int ath_rx_tasklet(struct ath_softc *sc,
 				rx_status.flag |= RX_FLAG_DECRYPTED;
 		}
 
+		if (rx_status.flag & RX_FLAG_DECRYPTED) {
+			/* Hardware verifies Michael MIC in unfragmented
+			 * frames, so there is no need to do software
+			 * verification for them. */
+			__le16 fc = hdr->frame_control;
+			u16 sc = le16_to_cpu(hdr->seq_ctrl);
+			if (!ieee80211_has_morefrags(fc) &&
+			    (sc & IEEE80211_SCTL_FRAG) == 0)
+				rx_status.flag |= RX_FLAG_MMIC_VERIFIED;
+		}
+
 		/* Send the frame to mac80211 */
 		__ieee80211_rx(sc->hw, skb, &rx_status);
 
drivers/net/wireless/ath9k/xmit.c +8 -0
@@ -1711,6 +1711,14 @@ static int ath_tx_setup_buffer(struct at
 
 	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
 		bf->bf_frmlen += tx_info->control.hw_key->icv_len;
+		if (bf->bf_keytype == ATH9K_KEY_TYPE_TKIP &&
+		    !ieee80211_has_morefrags(fc)) {
+			u16 sc = le16_to_cpu(hdr->seq_ctrl);
+			if ((sc & IEEE80211_SCTL_FRAG) == 0) {
+				 /* Michael MIC in hardware */
+				bf->bf_frmlen += 8;
+			}
+		}
 		bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
 	} else {
 		bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
maintainer
#1 lore raw
Quoted 15 lines · Jouni Malinen

mac80211 used to allow drivers to indicate that Michael MIC has already been verified in received frames to allow the somewhat heavy operation of validating this in software to be avoided. This disappeared as part of hardware crypto flag rework (commit 7848ba7d7a010ccb265617fc2bc053e2bdf06f48). The changes below propose a bit different mechanism for achieving the same benefit for host CPU with wlan designs that can verify Michael MIC for unfragmented frames in hardware.

I'm also including a patch to ath9k to start using this new mechanism and move Michael MIC processing to hardware for both TX and RX whenever possible. It seems to work based on minimal testing, but I do not want to submit it to be merged before more thorough testing has taken place.

Quoted 7 lines

Some hardware acceleration designs for TKIP take care of Michael MIC verification in received frames (well, at least for frames that were not fragmented). Add an RX status flag to allow the expensive software validation of the Michael MIC to be skipped in cases where it has already been verified in hardware.

I probably thought you'd just strip it in that case, but this seems fine too.

johannes