Skip to contentSkip to conversation

more key handling updates

PATCH In review Johannes Berg 3 participants 30 messages Aug 24, 2007 – Aug 28, 2007

Subsystems (3)
lore
Share & tools
lore

Johannes Berg

author maintainer
#0 lore raw

cover more key handling updates

This patch series updates mac80211's and cfg80211's key handling and adds some documentation (more to follow.)

johannes

author maintainer
#1 lore raw

PATCH 1/15 mac80211: improve key selection comment

When I changed the code there I forgot to mention what happens with multicast frames in a regular BSS and keep wondering myself if the code is correct. Add appropriate comments.

---
 net/mac80211/rx.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
net/mac80211/rx.c +9 -2
@@ -338,16 +338,23 @@ ieee80211_rx_h_load_key(struct ieee80211
 	 * frames can also use key indizes like GTKs. Hence, if we don't
 	 * have a PTK/STK we check the key index for a WEP key.
 	 *
+	 * Note that in a regular BSS, multicast frames are sent by the
+	 * AP only, associated stations unicast the frame to the AP first
+	 * which then multicasts it on their behalf.
+	 *
 	 * There is also a slight problem in IBSS mode: GTKs are negotiated
 	 * with each station, that is something we don't currently handle.
+	 * The spec seems to expect that one negotiates the same key with
+	 * every station but there's no such requirement; VLANs could be
+	 * possible.
 	 */
 
 	if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
 		return TXRX_CONTINUE;
 
 	/*
-	 * No point in finding a key if the frame is neither
-	 * addressed to us nor a multicast frame.
+	 * No point in finding a key if the frame is neither addressed to
+	 * us nor a multicast frame (ra_match is true for multicast frames.)
 	 */
 	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
 		return TXRX_DROP;
author maintainer
#2 lore raw

PATCH 2/15 mac80211: rework hardware crypto flags

In reply to Johannes Berg

This patch reworks the various hardware crypto related flags to make them more local, i.e. put them with each key or each packet instead of into the hw struct.

---
 drivers/net/wireless/adm8211.c                  |    2 
 drivers/net/wireless/b43/main.c                 |    4 -
 drivers/net/wireless/b43/xmit.c                 |   28 -------------
 drivers/net/wireless/iwl-base.c                 |    5 +-
 drivers/net/wireless/p54common.c                |    3 -
 drivers/net/wireless/rtl8187_dev.c              |    3 -
 drivers/net/wireless/zd1211rw-mac80211/zd_mac.c |    1 
 include/net/mac80211.h                          |   49 +++++++-----------------
 net/mac80211/rx.c                               |   24 ++++-------
 net/mac80211/tx.c                               |    5 --
 net/mac80211/wpa.c                              |   43 ++++++---------------
 11 files changed, 49 insertions(+), 118 deletions(-)
include/net/mac80211.h +15 -34
@@ -243,6 +243,8 @@ struct ieee80211_rx_status {
 #define RX_FLAG_MMIC_ERROR	(1<<0)
 #define RX_FLAG_DECRYPTED	(1<<1)
 #define RX_FLAG_RADIOTAP	(1<<2)
+#define RX_FLAG_MMIC_STRIPPED	(1<<3)
+#define RX_FLAG_IV_STRIPPED	(1<<4)
 	int flag;
 };
 
@@ -405,6 +407,16 @@ typedef enum {
  * that situation it should reject that key.
  */
 #define IEEE80211_KEY_FLAG_WMM_STA	(1<<0)
+/*
+ * This flag should be set by the driver if it requires
+ * IV generation in software for this key.
+ */
+#define IEEE80211_KEY_FLAG_GENERATE_IV	(1<<1)
+/*
+ * This flag should be set by the driver if it requires
+ * MMIC generation in software for this key.
+ */
+#define IEEE80211_KEY_FLAG_GENERATE_MMIC (1<<2)
 
 struct ieee80211_key_conf {
 	/*
@@ -474,17 +486,7 @@ struct ieee80211_hw {
 	 */
 #define IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE (1<<1)
 
-	/*
-	 * Some devices handle decryption internally and do not
-	 * indicate whether the frame was encrypted (unencrypted frames
-	 * will be dropped by the hardware, unless specifically allowed
-	 * through.)
-	 * It is permissible to not handle all encrypted frames and fall
-	 * back to software encryption; however, if this flag is set
-	 * unencrypted frames must be dropped unless the driver is told
-	 * otherwise via the set_ieee8021x() callback.
-	 */
-#define IEEE80211_HW_DEVICE_HIDES_WEP (1<<2)
+/* hole at 2 */
 
 	/* Whether RX frames passed to ieee80211_rx() include FCS in the end */
 #define IEEE80211_HW_RX_INCLUDES_FCS (1<<3)
@@ -497,32 +499,13 @@ struct ieee80211_hw {
 	 * can fetch them with ieee80211_get_buffered_bc(). */
 #define IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING (1<<4)
 
-	/*
-	 * This flag is only relevant if hardware encryption is used.
-	 * If set, it has two meanings:
-	 *  1) the IV and ICV are present in received frames that have
-	 *     been decrypted (unless IEEE80211_HW_DEVICE_HIDES_WEP is
-	 *     also set)
-	 *  2) on transmission, the IV should be generated in software.
-	 *
-	 * Please let us know if you *don't* use this flag, the stack would
-	 * really like to be able to get the IV to keep key statistics
-	 * accurate.
-	 */
-#define IEEE80211_HW_WEP_INCLUDE_IV (1<<5)
+/* hole at 5 */
 
 /* hole at 6 */
 
 /* hole at 7 */
 
-	/*
-	 * Some devices handle Michael MIC internally and do not include MIC in
-	 * the received packets passed up. This flag must be set for such
-	 * devices. The 'encryption' frame control bit is expected to be still
-	 * set in the IEEE 802.11 header with this option unlike with the
-	 * IEEE80211_HW_DEVICE_HIDES_WEP flag.
-	 */
-#define IEEE80211_HW_DEVICE_STRIPS_MIC (1<<8)
+/* hole at 8 */
 
 	/* Device is capable of performing full monitor mode even during
 	 * normal operation. */
@@ -536,8 +519,6 @@ struct ieee80211_hw {
 	 * specified in the device's EEPROM */
 #define IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED (1<<11)
 
-	/* calculate Michael MIC for an MSDU when doing hwcrypto */
-#define IEEE80211_HW_TKIP_INCLUDE_MMIC (1<<12)
 	/* Do TKIP phase1 key mixing in stack to support cards only do
 	 * phase2 key mixing when doing hwcrypto */
 #define IEEE80211_HW_TKIP_REQ_PHASE1_KEY (1<<13)
net/mac80211/wpa.c +14 -29

97 lines not on this page · raw message

net/mac80211/rx.c +10 -14
@@ -370,7 +370,8 @@ ieee80211_rx_h_load_key(struct ieee80211
 		 * we somehow allow the driver to tell us which key
 		 * the hardware used if this flag is set?
 		 */
-		if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
+		if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+		    (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
 			return TXRX_CONTINUE;
 
 		hdrlen = ieee80211_get_hdrlen(rx->fc);
@@ -547,8 +548,8 @@ ieee80211_rx_h_wep_weak_iv_detection(str
 		return TXRX_CONTINUE;
 
 	/* Check for weak IVs, if hwaccel did not remove IV from the frame */
-	if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) ||
-	    !(rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+	if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
+	    !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED))
 		if (ieee80211_wep_is_weak_iv(rx->skb, rx->key))
 			rx->sta->wep_weak_iv_count++;
 
@@ -572,15 +573,14 @@ ieee80211_rx_h_wep_decrypt(struct ieee80
 		return TXRX_DROP;
 	}
 
-	if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) ||
-	    !(rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
+	if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
 		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
 			if (net_ratelimit())
 				printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
 				       "failed\n", rx->dev->name);
 			return TXRX_DROP;
 		}
-	} else if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+	} else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
 		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
 		/* remove ICV */
 		skb_trim(rx->skb, rx->skb->len - 4);
@@ -911,13 +911,10 @@ static ieee80211_txrx_result
 ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
 {
 	/*
-	 * Pass through unencrypted frames if the hardware might have
-	 * decrypted them already without telling us, but that can only
-	 * be true if we either didn't find a key or the found key is
-	 * uploaded to the hardware.
+	 * Pass through unencrypted frames if the hardware has
+	 * decrypted them already.
 	 */
-	if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) &&
-	    (!rx->key || (rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)))
+	if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
 		return TXRX_CONTINUE;
 
 	/* Drop unencrypted frames if key is set. */
@@ -1362,8 +1359,7 @@ static void ieee80211_rx_michael_mic_rep
 		goto ignore;
 	}
 
-	if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
-	    rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) {
+	if (rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) {
 		/* AP with Pairwise keys support should never receive Michael
 		 * MIC errors for non-zero keyidx because these are reserved
 		 * for group keys and only the AP is sending real multicast
net/mac80211/tx.c +2 -3
@@ -541,9 +541,8 @@ static int wep_encrypt_skb(struct ieee80
 			return -1;
 	} else {
 		tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
-		if (tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
-			if (ieee80211_wep_add_iv(tx->local, skb, tx->key) ==
-			    NULL)
+		if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
+			if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
 				return -1;
 		}
 	}
drivers/net/wireless/iwl-base.c +3 -2
@@ -7906,6 +7906,8 @@ static int iwl_mac_set_key(struct ieee80
 		 * conf->sw_decrypt = 0;
 		 */
 		IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
+
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 	}
 
 	IWL_DEBUG_MAC80211("leave\n");
@@ -9134,8 +9136,7 @@ static int iwl_pci_probe(struct pci_dev 
 	hw->max_signal = 100;	/* link quality indication (%) */
 
 	/* Tell mac80211 our Tx characteristics */
-	hw->flags = IEEE80211_HW_WEP_INCLUDE_IV |
-	    IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+	hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
 
 	hw->queues = 4;
 #if IWL == 4965
drivers/net/wireless/rtl8187_dev.c +1 -2
@@ -605,8 +605,7 @@ static int __devinit rtl8187_probe(struc
 	priv->modes[1].channels = priv->channels;
 	priv->mode = IEEE80211_IF_TYPE_MGMT;
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		     IEEE80211_HW_RX_INCLUDES_FCS |
-		     IEEE80211_HW_WEP_INCLUDE_IV;
+		     IEEE80211_HW_RX_INCLUDES_FCS;
 	dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
 	dev->queues = 1;
 	dev->max_rssi = 65;
drivers/net/wireless/adm8211.c +1 -1
@@ -1953,7 +1953,7 @@ static int __devinit adm8211_probe(struc
 	SET_IEEE80211_PERM_ADDR(dev, perm_addr);
 
 	dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
-	dev->flags = IEEE80211_HW_WEP_INCLUDE_IV;
+	dev->flags = 0;
 	// however, IEEE80211_HW_RX_INCLUDES_FCS in promisc mode
 
 	dev->channel_change_time = 1000;
drivers/net/wireless/b43/main.c +2 -2
@@ -2967,6 +2967,7 @@ static int b43_dev_set_key(struct ieee80
 			b43_hf_write(dev,
 				     b43_hf_read(dev) & ~B43_HF_USEDEFKEYS);
 		}
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 		break;
 	case DISABLE_KEY: {
 		static const u8 zero[B43_SEC_KEYSIZE] = { 0 };
@@ -3913,8 +3914,7 @@ static int b43_wireless_init(struct ssb_
 
 	/* fill hw info */
 	hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-	    IEEE80211_HW_MONITOR_DURING_OPER |
-	    IEEE80211_HW_DEVICE_HIDES_WEP | IEEE80211_HW_WEP_INCLUDE_IV;
+		    IEEE80211_HW_MONITOR_DURING_OPER;
 	hw->max_signal = 100;
 	hw->max_rssi = -110;
 	hw->max_noise = -110;
drivers/net/wireless/b43/xmit.c +0 -28
@@ -486,8 +486,6 @@ void b43_rx(struct b43_wldev *dev, struc
 	if ((macstat & B43_RX_MAC_DEC) && !(macstat & B43_RX_MAC_DECERR)) {
 		unsigned int keyidx;
 		int wlhdr_len;
-		int iv_len;
-		int icv_len;
 
 		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
 			  >> B43_RX_MAC_KEYIDX_SHIFT);
@@ -498,38 +496,12 @@ void b43_rx(struct b43_wldev *dev, struc
 		B43_WARN_ON(keyidx >= dev->max_nr_keys);
 
 		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
-			/* Remove PROTECTED flag to mark it as decrypted. */
-			B43_WARN_ON(!(fctl & IEEE80211_FCTL_PROTECTED));
-			fctl &= ~IEEE80211_FCTL_PROTECTED;
-			wlhdr->frame_control = cpu_to_le16(fctl);
-
 			wlhdr_len = ieee80211_get_hdrlen(fctl);
 			if (unlikely(skb->len < (wlhdr_len + 3))) {
 				b43dbg(dev->wl,
 				       "RX: Packet size underrun (3)\n");
 				goto drop;
 			}
-			if (skb->data[wlhdr_len + 3] & (1 << 5)) {
-				/* The Ext-IV Bit is set in the "KeyID"
-				 * octet of the IV.
-				 */
-				iv_len = 8;
-				icv_len = 8;
-			} else {
-				iv_len = 4;
-				icv_len = 4;
-			}
-			if (unlikely(skb->len < (wlhdr_len + iv_len + icv_len))) {
-				b43dbg(dev->wl,
-				       "RX: Packet size underrun (4)\n");
-				goto drop;
-			}
-			/* Remove the IV */
-			memmove(skb->data + iv_len, skb->data, wlhdr_len);
-			skb_pull(skb, iv_len);
-			/* Remove the ICV */
-			skb_trim(skb, skb->len - icv_len);
-
 			status.flag |= RX_FLAG_DECRYPTED;
 		}
 	}
drivers/net/wireless/p54common.c +1 -2
@@ -892,8 +892,7 @@ struct ieee80211_hw *p54_init_common(siz
 	priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
 	priv->modes[0].channels = priv->channels;
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
-		    IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_WEP_INCLUDE_IV;
+		    IEEE80211_HW_RX_INCLUDES_FCS;
 	dev->channel_change_time = 1000;	/* TODO: find actual value */
 	dev->max_rssi = 100;
 
drivers/net/wireless/zd1211rw-mac80211/zd_mac.c +0 -1
@@ -879,7 +879,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(str
 	mac->modes[1].channels = mac->channels;
 
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		     IEEE80211_HW_WEP_INCLUDE_IV |
 		     IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
 	hw->max_rssi = 100;
 	hw->max_signal = 100;
author maintainer
#3 lore raw

PATCH 3/15 mac80211: remove set_key_idx callback

In reply to Johannes Berg

No existing drivers use this callback, hence there's no telling how it might be used. In fact, it is unlikely to be of much use as-is because the default key index isn't something that the driver can do much with without knowing which interface it was for etc. And if it needs the key index for the transmitted frame, it can get it by keeping a reference to the key_conf structure and looking it up by hw_key_idx.

---
 include/net/mac80211.h |   13 -------------
 net/mac80211/key.c     |    4 ----
 2 files changed, 17 deletions(-)
include/net/mac80211.h +0 -13
@@ -669,19 +669,6 @@ struct ieee80211_ops {
 		       const u8 *local_address, const u8 *address,
 		       struct ieee80211_key_conf *key);
 
-	/*
-	 * Set TX key index for default/broadcast keys. This is needed in cases
-	 * where wlan card is doing full WEP/TKIP encapsulation (wep_include_iv
-	 * is not set), in other cases, this function pointer can be set to
-	 * NULL since the IEEE 802.11 module takes care of selecting the key
-	 * index for each TX frame.
-	 *
-	 * TODO: If you use this callback in your driver tell us if you need
-	 *	 any other information from it to make it easier, like the
-	 *	 key_conf instead.
-	 */
-	int (*set_key_idx)(struct ieee80211_hw *hw, int idx);
-
 	/* Enable/disable IEEE 802.1X. This item requests wlan card to pass
 	 * unencrypted EAPOL-Key frames even when encryption is configured.
 	 * If the wlan card does not require such a configuration, this
net/mac80211/key.c +0 -4
@@ -264,10 +264,6 @@ void ieee80211_set_default_key(struct ie
 
 		if (sdata->default_key)
 			ieee80211_debugfs_key_add_default(sdata);
-
-		if (sdata->local->ops->set_key_idx)
-			sdata->local->ops->set_key_idx(
-				local_to_hw(sdata->local), idx);
 	}
 }
 
author maintainer
#4 lore raw

PATCH 4/15 mac80211: some more documentation

In reply to Johannes Berg

This patch formats some documentation in mac80211.h into kerneldoc and also adds some more explanations for hardware crypto.

---
 include/net/mac80211.h |  160 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 109 insertions(+), 51 deletions(-)
include/net/mac80211.h +109 -51
@@ -227,24 +227,56 @@ struct ieee80211_tx_control {
 	int ifindex;	/* internal */
 };
 
-/* Receive status. The low-level driver should provide this information
- * (the subset supported by hardware) to the 802.11 code with each received
- * frame. */
+
+/**
+ * enum mac80211_rx_flags - receive flags
+ *
+ * These flags are used with the @flag member of &struct ieee80211_rx_status.
+ * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame.
+ *	Use together with %RX_FLAG_MMIC_STRIPPED.
+ * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware.
+ * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header.
+ * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame,
+ *	verification has been done by the hardware.
+ * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame.
+ *	If this flag is set, the stack cannot do any replay detection
+ *	hence the driver or hardware will have to do that.
+ */
+enum mac80211_rx_flags {
+	RX_FLAG_MMIC_ERROR	= 1<<0,
+	RX_FLAG_DECRYPTED	= 1<<1,
+	RX_FLAG_RADIOTAP	= 1<<2,
+	RX_FLAG_MMIC_STRIPPED	= 1<<3,
+	RX_FLAG_IV_STRIPPED	= 1<<4,
+};
+
+/**
+ * struct ieee80211_rx_status - receive status
+ *
+ * The low-level driver should provide this information (the subset
+ * supported by hardware) to the 802.11 code with each received
+ * frame.
+ * @mactime: MAC timestamp as defined by 802.11
+ * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+ * @channel: channel the radio was tuned to
+ * @phymode: active PHY mode
+ * @ssi: signal strength when receiving this frame
+ * @signal: used as 'qual' in statistics reporting
+ * @noise: PHY noise when receiving this frame
+ * @antenna: antenna used
+ * @rate: data rate
+ * @flag: %RX_FLAG_*
+ */
 struct ieee80211_rx_status {
 	u64 mactime;
-	int freq; /* receive frequency in Mhz */
+	int freq;
 	int channel;
 	int phymode;
 	int ssi;
-	int signal; /* used as qual in statistics reporting */
+	int signal;
 	int noise;
 	int antenna;
 	int rate;
-#define RX_FLAG_MMIC_ERROR	(1<<0)
-#define RX_FLAG_DECRYPTED	(1<<1)
-#define RX_FLAG_RADIOTAP	(1<<2)
-#define RX_FLAG_MMIC_STRIPPED	(1<<3)
-#define RX_FLAG_IV_STRIPPED	(1<<4)
 	int flag;
 };
 
@@ -394,68 +426,89 @@ struct ieee80211_if_conf {
 	struct ieee80211_tx_control *beacon_control;
 };
 
-typedef enum {
+/**
+ * enum ieee80211_key_alg - key algorithm
+ * @ALG_NONE: Unset key algorithm, will never be passed to the driver
+ * @ALG_WEP: WEP40 or WEP104
+ * @ALG_TKIP: TKIP
+ * @ALG_CCMP: CCMP (AES)
+ */
+typedef enum ieee80211_key_alg {
 	ALG_NONE,
 	ALG_WEP,
 	ALG_TKIP,
 	ALG_CCMP,
 } ieee80211_key_alg;
 
-/*
- * This flag indiciates that the station this key is being
- * configured for may use QoS. If your hardware cannot handle
- * that situation it should reject that key.
- */
-#define IEEE80211_KEY_FLAG_WMM_STA	(1<<0)
-/*
- * This flag should be set by the driver if it requires
- * IV generation in software for this key.
- */
-#define IEEE80211_KEY_FLAG_GENERATE_IV	(1<<1)
-/*
- * This flag should be set by the driver if it requires
- * MMIC generation in software for this key.
- */
-#define IEEE80211_KEY_FLAG_GENERATE_MMIC (1<<2)
 
+/**
+ * enum ieee80211_key_flags - key flags
+ *
+ * These flags are used for communication about keys between the driver
+ * and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
+ *
+ * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates
+ *	that the STA this key will be used with could be using QoS.
+ * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
+ *	driver to indicate that it requires IV generation for this
+ *	particular key.
+ * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by
+ *	the driver for a TKIP key if it requires Michael MIC
+ *	generation in software.
+ */
+enum ieee80211_key_flags {
+	IEEE80211_KEY_FLAG_WMM_STA	= 1<<0,
+	IEEE80211_KEY_FLAG_GENERATE_IV	= 1<<1,
+	IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
+};
+
+/**
+ * struct ieee80211_key_conf - key information
+ *
+ * This key information is given by mac80211 to the driver by
+ * the set_key() callback in &struct ieee80211_ops.
+ *
+ * @hw_key_idx: To be set by the driver, this is the key index the driver
+ *	wants to be given when a frame is transmitted and needs to be
+ *	encrypted in hardware. It defaults to %HW_KEY_IDX_INVALID which
+ *	the driver may not use.
+ * @alg: The key algorithm.
+ * @driver_keylist: for use by the driver
+ * @flags: key flags, see &enum ieee80211_key_flags.
+ * @keyidx: the key index (0-3)
+ * @keylen: key material length
+ * @key: key material
+ */
 struct ieee80211_key_conf {
-	/*
-	 * To be set by the driver to the key index it would like to
-	 * get in the ieee80211_tx_control.key_idx which defaults
-	 * to HW_KEY_IDX_INVALID so that shouldn't be used.
-	 */
 	int hw_key_idx;
-
-	/* key algorithm, ALG_NONE should never be seen by the driver */
 	ieee80211_key_alg alg;
-
-	/*
-	 * for use by the driver, named this way to avoid
-	 * accidental use in the stack
-	 */
 	struct list_head driver_keylist;
-
-	/* key flags, see above */
 	u8 flags;
-
-	/* key index: 0-3 */
 	s8 keyidx;
-
-	/* length of key material */
 	u8 keylen;
-
-	/* the key material */
 	u8 key[0];
 };
 
 #define IEEE80211_SEQ_COUNTER_RX	0
 #define IEEE80211_SEQ_COUNTER_TX	1
 
-typedef enum {
+/**
+ * enum set_key_cmd - key command
+ *
+ * Used with the set_key() callback in &struct ieee80211_ops, this
+ * indicates whether a key is being removed or added.
+ *
+ * @SET_KEY: a key is set
+ * @DISABLE_KEY: a key must be disabled
+ */
+typedef enum set_key_cmd {
 	SET_KEY, DISABLE_KEY,
 } set_key_cmd;
 
-/* This is driver-visible part of the per-hw state the stack keeps. */
+/**
+ * struct ieee80211_hw - hardware information and state
+ * TODO: move documentation into kernel-doc format
+ */
 struct ieee80211_hw {
 	/* points to the cfg80211 wiphy for this piece. Note
 	 * that you must fill in the perm_addr and dev fields
@@ -655,6 +708,11 @@ struct ieee80211_ops {
 	 * assigned to something other than HW_KEY_IDX_INVALID. When the cmd
 	 * is DISABLE_KEY then it must succeed.
 	 *
+	 * Note that it is permissible to not decrypt a frame even if a key
+	 * for it has been uploaded to hardware, the stack will not make any
+	 * decision based on whether a key has been uploaded or not but rather
+	 * based on the receive flags.
+	 *
 	 * This callback can sleep, and is only called between add_interface
 	 * and remove_interface calls, i.e. while the interface with the
 	 * given local_address is enabled.
@@ -1062,13 +1120,13 @@ ieee80211_get_mc_list_item(struct ieee80
 /**
  * ieee80211_key_removed - the driver removed a key from hardware accel
  *
- * @keyconf: The key config structure for the key that was removed.
- *
  * Call this function if for some reason you had to remove a key
  * from the hardware acceleration completely.
  * Note that after calling this function you will not get a
  * DISABLE_KEY notification via set_key() any more for this key,
  * it is assumed that you've removed it already.
+ *
+ * @keyconf: The key config structure for the key that was removed.
  */
 void ieee80211_key_removed(struct ieee80211_key_conf *keyconf);
 
author maintainer
#5 lore raw

PATCH 5/15 mac80211: remove HW_KEY_IDX_INVALID

In reply to Johannes Berg

This patch makes the mac80211/driver interface rely only on the IEEE80211_TXCTL_DO_NOT_ENCRYPT flag to signal to the driver whether a frame should be encrypted or not, since mac80211 internally no longer relies on HW_KEY_IDX_INVALID either this removes it, changes the key index to be a u8 in all places and makes the full range of the value available to drivers.

---
Changes since v1:
* use a u8 instead of an int
* reorder some fields for better space usage (less padding)

 include/net/mac80211.h |   19 +++++++++----------
 net/mac80211/key.c     |    5 -----
 net/mac80211/tx.c      |    7 +++----
 net/mac80211/wpa.c     |    8 ++++----
 4 files changed, 16 insertions(+), 23 deletions(-)
include/net/mac80211.h +9 -10
@@ -167,7 +167,6 @@ struct ieee80211_low_level_stats {
 /* Transmit control fields. This data structure is passed to low-level driver
  * with each TX frame. The low-level driver is responsible for configuring
  * the hardware to use given values (depending on what is supported). */
-#define HW_KEY_IDX_INVALID -1
 
 struct ieee80211_tx_control {
 	int tx_rate; /* Transmit rate, given as the hw specific value for the
@@ -200,13 +199,13 @@ struct ieee80211_tx_control {
 						  * long retry value */
 	u32 flags;			       /* tx control flags defined
 						* above */
+	u8 key_idx;		/* keyidx from hw->set_key(), undefined if
+				 * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
 	u8 retry_limit;		/* 1 = only first attempt, 2 = one retry, ..
 				 * This could be used when set_retry_limit
 				 * is not implemented by the driver */
 	u8 power_level;		/* per-packet transmit power level, in dBm */
 	u8 antenna_sel_tx; 	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
-	s8 key_idx;		/* HW_KEY_IDX_INVALID = do not encrypt,
-				 * other values: keyidx from hw->set_key() */
 	u8 icv_len;		/* length of the ICV/MIC field in octets */
 	u8 iv_len;		/* length of the IV field in octets */
 	u8 tkip_key[16];	/* generated phase2/phase1 key for hw TKIP */
@@ -470,8 +469,7 @@ enum ieee80211_key_flags {
  *
  * @hw_key_idx: To be set by the driver, this is the key index the driver
  *	wants to be given when a frame is transmitted and needs to be
- *	encrypted in hardware. It defaults to %HW_KEY_IDX_INVALID which
- *	the driver may not use.
+ *	encrypted in hardware.
  * @alg: The key algorithm.
  * @driver_keylist: for use by the driver
  * @flags: key flags, see &enum ieee80211_key_flags.
@@ -480,9 +478,9 @@ enum ieee80211_key_flags {
  * @key: key material
  */
 struct ieee80211_key_conf {
-	int hw_key_idx;
-	ieee80211_key_alg alg;
 	struct list_head driver_keylist;
+	ieee80211_key_alg alg;
+	u8 hw_key_idx;
 	u8 flags;
 	s8 keyidx;
 	u8 keylen;
@@ -704,9 +702,10 @@ struct ieee80211_ops {
 	 * remove the key for transmission.
 	 *
 	 * Return 0 if the key is now in use, -EOPNOTSUPP or -ENOSPC if it
-	 * couldn't be added; if you return 0 then hw_key_idx must be
-	 * assigned to something other than HW_KEY_IDX_INVALID. When the cmd
-	 * is DISABLE_KEY then it must succeed.
+	 * couldn't be added; if you return 0 then hw_key_idx must be assigned
+	 * to the hardware key index, you are free to use the full u8 range.
+	 *
+	 * When the cmd is DISABLE_KEY then it must succeed.
 	 *
 	 * Note that it is permissible to not decrypt a frame even if a key
 	 * for it has been uploaded to hardware, the stack will not make any
net/mac80211/key.c +0 -5
@@ -69,8 +69,6 @@ static void ieee80211_key_enable_hw_acce
 				       key->sdata->dev->dev_addr, addr,
 				       &key->conf);
 
-	WARN_ON(!ret && (key->conf.hw_key_idx == HW_KEY_IDX_INVALID));
-
 	if (!ret)
 		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
 
@@ -105,7 +103,6 @@ static void ieee80211_key_disable_hw_acc
 		       key->conf.keyidx, MAC_ARG(addr), ret);
 
 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-	key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
 }
 
 /*
@@ -122,7 +119,6 @@ void ieee80211_key_removed(struct ieee80
 		return;
 
 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-	key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
 }
 
 struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
@@ -144,7 +140,6 @@ struct ieee80211_key *ieee80211_key_allo
 	 * Default to software encryption; we'll later upload the
 	 * key to the hardware if possible.
 	 */
-	key->conf.hw_key_idx = HW_KEY_IDX_INVALID;
 	key->conf.flags = 0;
 	key->flags = 0;
 
net/mac80211/wpa.c +4 -4
@@ -136,7 +136,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
 		printk(KERN_INFO "%s: WPA testing - corrupting TX Michael MIC "
 		       "for STA " MAC_FMT "\n",
 		       tx->dev->name, MAC_ARG(tx->sta->addr));
-		tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
 		tx->sta->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_MIC;
 		tx->wpa_test = 1;
 		mic[0]++;
@@ -144,7 +144,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
 		   tx->local->wpa_trigger & WPA_TRIGGER_FAIL_TX_MIC) {
 		printk(KERN_INFO "%s: WPA testing - corrupting TX Michael MIC "
 		       "for Group Key\n", tx->dev->name);
-		tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
 		tx->local->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_MIC;
 		tx->wpa_test = 1;
 		mic[0]++;
@@ -415,7 +415,7 @@ ieee80211_tx_h_tkip_encrypt(struct ieee8
 		printk(KERN_INFO "%s: WPA testing - corrupting TX TKIP ICV "
 		       "for STA " MAC_FMT "\n",
 		       tx->dev->name, MAC_ARG(tx->sta->addr));
-		tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
 		tx->sta->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_ICV;
 		skb->data[skb->len - 1]++;
 	} else if (!(tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
@@ -423,7 +423,7 @@ ieee80211_tx_h_tkip_encrypt(struct ieee8
 		printk(KERN_INFO "%s: WPA testing - corrupting TX TKIP ICV "
 		       "for Group Key\n",
 		       tx->dev->name);
-		tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
 		tx->local->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_ICV;
 		skb->data[skb->len - 1]++;
 	}
net/mac80211/tx.c +3 -4
@@ -426,8 +426,6 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t
 static ieee80211_txrx_result
 ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
 {
-	tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
-
 	if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
 		tx->key = NULL;
 	else if (tx->sta && tx->sta->key)
@@ -438,8 +436,10 @@ ieee80211_tx_h_select_key(struct ieee802
 		 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
 		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
 		return TXRX_DROP;
-	} else
+	} else {
 		tx->key = NULL;
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+	}
 
 	if (tx->key) {
 		tx->key->tx_rx_count++;
@@ -831,7 +831,6 @@ __ieee80211_parse_tx_radiotap(
 	 */
 
 	control->retry_limit = 1; /* no retry */
-	control->key_idx = HW_KEY_IDX_INVALID;
 	control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
 			    IEEE80211_TXCTL_USE_CTS_PROTECT);
 	control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT |
#6 lore raw

Re: [PATCH 05/15] mac80211: remove HW_KEY_IDX_INVALID

Johannes Berg wrote:

The following hunk in wireless-dev/include/net/mac80211.h

@@ -200,13 +199,13 @@ struct ieee80211_tx_control {
* long retry value */
u32 flags; /* tx control flags defined
* above */
+ u8 key_idx; /* keyidx from hw->set_key(), undefined if
+ * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
u8 retry_limit; /* 1 = only first attempt, 2 = one retry, ..
* This could be used when set_retry_limit
* is not implemented by the driver */
u8 power_level; /* per-packet transmit power level, in dBm */
u8 antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
- s8 key_idx; /* HW_KEY_IDX_INVALID = do not encrypt,
- * other values: keyidx from hw->set_key() */
u8 icv_len; /* length of the ICV/MIC field in octets */
u8 iv_len; /* length of the IV field in octets */
u8 tkip_key[16]; /* generated phase2/phase1 key for hw TKIP */

leads to a compiler warning "warning: comparison is always true due to limited range of data type" for b43 and b43legacy on the fiollowing statement.

        int use_encryption = ((!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
                              && (txctl->key_idx >= 0));

What did a negative key_idx mean before? How is that condition represented now, or is it safe to drop the entire portion following the &&?

Thanks,

Larry

#7 lore raw

Re: [PATCH 05/15] mac80211: remove HW_KEY_IDX_INVALID

Quoted 21 lines · On Friday 24 August 2007 19:14:06 Larry Finger wrote:

Johannes Berg wrote:

The following hunk in wireless-dev/include/net/mac80211.h

include/net/mac80211.h +2 -2
@@ -200,13 +199,13 @@ struct ieee80211_tx_control {
  						  * long retry value */
  	u32 flags;			       /* tx control flags defined
  						* above */
+	u8 key_idx;		/* keyidx from hw->set_key(), undefined if
+				 * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
  	u8 retry_limit;		/* 1 = only first attempt, 2 = one retry, ..
  				 * This could be used when set_retry_limit
  				 * is not implemented by the driver */
  	u8 power_level;		/* per-packet transmit power level, in dBm */
  	u8 antenna_sel_tx; 	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
-	s8 key_idx;		/* HW_KEY_IDX_INVALID = do not encrypt,
-				 * other values: keyidx from hw->set_key() */
  	u8 icv_len;		/* length of the ICV/MIC field in octets */
  	u8 iv_len;		/* length of the IV field in octets */
  	u8 tkip_key[16];	/* generated phase2/phase1 key for hw TKIP */
Quoted 8 lines

leads to a compiler warning "warning: comparison is always true due to limited range of data type" for b43 and b43legacy on the fiollowing statement.

         int use_encryption = ((!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
                               && (txctl->key_idx >= 0));

What did a negative key_idx mean before? How is that condition represented now, or is it safe to drop the entire portion following the &&?

Simply drop the test for key_idx>=0.
It doesn't make sense to have two conditions in the tx control to indicate use of encryption, so the negative key index was removed and the DO_NOT_ENCRYPT flag is the one to test. So you should probably remove the use_encryption variable, too, and test the txctl->flags in the place where it's needed.

Signature · 1 line
Greetings Michael.
#8 lore raw

Re: [PATCH 05/15] mac80211: remove HW_KEY_IDX_INVALID

In reply to Johannes Berg

Johannes Berg wrote:

This patch breaks software encryption in my tests - WPA for b43, WPA and WEP for b43legacy. I haven't looked for the cause yet. That is my next step.

Larry

author maintainer
#9 lore raw

Re: [PATCH 05/15] mac80211: remove HW_KEY_IDX_INVALID

Quoted 2 lines · Larry Finger

This patch breaks software encryption in my tests - WPA for b43, WPA and WEP for b43legacy. I haven't looked for the cause yet. That is my next step.

The patch below appears necessary for b43 when I enable sw crypto, but you shouldn't be having such problems in b43legacy since you don't support crypto at all; or have you not removed the crypto related code from xmit.c?

johannes

---
 net/mac80211/tx.c |    9 +++++++++
 1 file changed, 9 insertions(+)
net/mac80211/tx.c +9 -0
@@ -722,6 +722,15 @@ ieee80211_tx_h_misc(struct ieee80211_txr
 		}
 	}
 
+	/*
+	 * Tell hardware to not encrypt when we had sw crypto.
+	 * Because we use the same flag to internally indicate that
+	 * no encryption should be done, we have to set it after all
+	 * crypto handlers to indicate that we want encryption.
+	 */
+	if (tx->key && !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+
 	return TXRX_CONTINUE;
 }
 
#10 lore raw

Re: [PATCH 05/15] mac80211: remove HW_KEY_IDX_INVALID

Quoted 8 lines · Johannes Berg
Quoted 1 line · Larry Finger

This patch breaks software encryption in my tests - WPA for b43, WPA and WEP for b43legacy. I haven't looked for the cause yet. That is my next step.

The patch below appears necessary for b43 when I enable sw crypto, but you shouldn't be having such problems in b43legacy since you don't support crypto at all; or have you not removed the crypto related code from xmit.c?

This fixes b43. It is a bit more difficult to test legacy, but it should be the same.

The code in xmit.c for legacy is essentially the same as for b43. It certainly could be trimmed a bit since no keys are ever set - routine set_key returns "no support".

Thanks,

Larry

author maintainer
#11 lore raw

Re: [PATCH 05/15] mac80211: remove HW_KEY_IDX_INVALID

Quoted 1 line · Larry Finger

This fixes b43. It is a bit more difficult to test legacy, but it should be the same.

Ok.

Quoted 2 lines

The code in xmit.c for legacy is essentially the same as for b43. It certainly could be trimmed a bit since no keys are ever set - routine set_key returns "no support".

Yeah, I figured you'd already gotten rid of that code in which case it shouldn't have made a difference.

johannes

author maintainer
#12 lore raw

PATCH 6/15 mac80211: remove TKIP mixing for hw accel again

In reply to Johannes Berg

The TKIP mixing code was added for the benefit of Intel's ipw3945 chipset but that code ended up not using it. We have previously identified many problems with this code and it crystallized that library functions for mixing are likely to handle this in much more generality and might allow b43 to take advantage of hardware acceleration for TKIP.

Due to these reasons, remove the TKIP mixing for hardware accelerated crypto operations.

---
 include/net/mac80211.h |    9 ---------
 net/mac80211/wpa.c     |   17 -----------------
 2 files changed, 26 deletions(-)
include/net/mac80211.h +0 -9
@@ -192,7 +192,6 @@ struct ieee80211_tx_control {
 #define IEEE80211_TXCTL_REQUEUE		(1<<7)
 #define IEEE80211_TXCTL_FIRST_FRAGMENT	(1<<8) /* this is a first fragment of
 						* the frame */
-#define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9)
 #define IEEE80211_TXCTL_LONG_RETRY_LIMIT (1<<10) /* this frame should be send
 						  * using the through
 						  * set_retry_limit configured
@@ -208,7 +207,6 @@ struct ieee80211_tx_control {
 	u8 antenna_sel_tx; 	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
 	u8 icv_len;		/* length of the ICV/MIC field in octets */
 	u8 iv_len;		/* length of the IV field in octets */
-	u8 tkip_key[16];	/* generated phase2/phase1 key for hw TKIP */
 	u8 queue;		/* hardware queue to use for this frame;
 				 * 0 = highest, hw->queues-1 = lowest */
 	u8 sw_retry_attempt;	/* number of times hw has tried to
@@ -570,13 +568,6 @@ struct ieee80211_hw {
 	 * specified in the device's EEPROM */
 #define IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED (1<<11)
 
-	/* Do TKIP phase1 key mixing in stack to support cards only do
-	 * phase2 key mixing when doing hwcrypto */
-#define IEEE80211_HW_TKIP_REQ_PHASE1_KEY (1<<13)
-	/* Do TKIP phase1 and phase2 key mixing in stack and send the generated
-	 * per-packet RC4 key with each TX frame when doing hwcrypto */
-#define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14)
-
 	/* The device capable of supporting 11n */
 #define IEEE80211_HW_SUPPORT_HT_MODE (1<<15)
 
net/mac80211/wpa.c +0 -17
@@ -297,7 +297,6 @@ skip_iv_inc:
 	    && !tx->wpa_test
 #endif /* CONFIG_HOSTAPD_WPA_TESTING */
 		) {
-		u32 flags = tx->local->hw.flags;
 		hdr = (struct ieee80211_hdr *)skb->data;
 
 		/* hwaccel - with preallocated room for IV */
@@ -307,22 +306,6 @@ skip_iv_inc:
 					    0x7f),
 				      (u8) key->u.tkip.iv16);
 
-		if (flags & IEEE80211_HW_TKIP_REQ_PHASE2_KEY)
-			ieee80211_tkip_gen_rc4key(key, hdr->addr2,
-						  tx->u.tx.control->tkip_key);
-		else if (flags & IEEE80211_HW_TKIP_REQ_PHASE1_KEY) {
-			if (key->u.tkip.iv16 == 0 ||
-			    !key->u.tkip.tx_initialized) {
-				ieee80211_tkip_gen_phase1key(key, hdr->addr2,
-					    (u16 *)tx->u.tx.control->tkip_key);
-				key->u.tkip.tx_initialized = 1;
-				tx->u.tx.control->flags |=
-					    IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY;
-			} else
-				tx->u.tx.control->flags &=
-					    ~IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY;
-		}
-
 		tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
 		return 0;
 	}
Acked-by on v1 6/15
#13 lore raw

Re: [PATCH 06/15] mac80211: remove TKIP mixing for hw accel again

Quoted 11 lines · On Friday 24 August 2007 14:27:11 Johannes Berg wrote:

The TKIP mixing code was added for the benefit of Intel's ipw3945 chipset but that code ended up not using it. We have previously identified many problems with this code and it crystallized that library functions for mixing are likely to handle this in much more generality and might allow b43 to take advantage of hardware acceleration for TKIP.

Due to these reasons, remove the TKIP mixing for hardware accelerated crypto operations.

Signature · 1 line
Greetings Michael.
author maintainer
#14 lore raw

PATCH 7/15 mac80211: ignore key index on pairwise key (WEP only)

In reply to Johannes Berg

From: Volker Braun <[email protected]>

Work-around for broken APs that use a non-zero key index for WEP pairwise keys. With this patch, WEP encryption only is exempt from providing a zero key index.

---
 net/mac80211/ieee80211_ioctl.c |   18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)
net/mac80211/ieee80211_ioctl.c +12 -6
@@ -385,17 +385,23 @@ static int ieee80211_set_encryption(stru
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
+	if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
+		printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
+		       dev->name, idx);
+		return -EINVAL;
+	}
+
 	if (is_broadcast_ether_addr(sta_addr)) {
 		sta = NULL;
-		if (idx >= NUM_DEFAULT_KEYS) {
-			printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
-			       dev->name, idx);
-			return -EINVAL;
-		}
 		key = sdata->keys[idx];
 	} else {
 		set_tx_key = 0;
-		if (idx != 0) {
+		/*
+		 * According to the standard, the key index of a pairwise
+		 * key must be zero. However, some AP are broken when it
+		 * comes to WEP key indices, so we work around this.
+		 */
+		if (idx != 0 && alg != ALG_WEP) {
 			printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
 			       "individual key\n", dev->name);
 			return -EINVAL;
author maintainer
#15 lore raw

PATCH 8/15 cfg80211: clean up key add/remove interface

In reply to Johannes Berg

This cleans up the key add/remove interface in both cfg80211 and nl80211.

---
 include/linux/nl80211.h |   51 ++++++++-----------
 include/net/cfg80211.h  |   13 +++-
 net/wireless/core.c     |    3 +
 net/wireless/nl80211.c  |  125 ++++++++++++++++++++++++++++++++----------------
 4 files changed, 118 insertions(+), 74 deletions(-)
include/linux/nl80211.h +21 -30
@@ -43,10 +43,10 @@
  *	%NL80211_ATTR_BSSID, %NL80211_ATTR_CHANNEL, %NL80211_ATTR_PHYMODE,
  *	and %NL80211_ATTR_IE may be given)
  * @NL80211_CMD_ADD_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
- * 	%NL80211_ATTR_KEY_ID, %NL80211_ATTR_KEY_TYPE, %NL80211_ATTR_MAC and
- *	%NL80211_ATTR_KEY_CIPHER attributes.
- * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_ID,
- *	%NL80211_ATTR_KEY_TYPE and %NL80211_ATTR_MAC or all keys.
+ *	%NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER
+ *	attributes.
+ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
+ *	or %NL80211_ATTR_MAC.
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
 enum nl80211_commands {
@@ -85,7 +85,9 @@ enum nl80211_commands {
 	NL80211_CMD_AP_UPDATE_STA,
 	NL80211_CMD_AP_GET_STA_INFO,
 	NL80211_CMD_AP_SET_RATESETS,
+	/* %input: ifindex, key_cipher, key_data, {key_idx, mac} */
 	NL80211_CMD_ADD_KEY,
+	/* %input: ifindex, key_idx|mac */
 	NL80211_CMD_DEL_KEY,
 
 	/* add commands here */
@@ -129,11 +131,13 @@ enum nl80211_commands {
  * @NL80211_ATTR_TRANSMIT_POWER: transmit power in mW
  * @NL80211_ATTR_FRAG_THRESHOLD: fragmentation threshold (bytes)
  * @NL80211_ATTR_FLAG_SCAN_ACTIVE: netlink flag indiciating active scan
- * @NL80211_ATTR_KEY_DATA: temporal key data
- * @NL80211_ATTR_KEY_ID: key ID (u8, 0-3)
- * @NL80211_ATTR_KEY_TYPE: key type (see &enum nl80211_keytype)
- * @NL80211_ATTR_MAC: MAC address
- * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32)
+ * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
+ *	16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ *	keys
+ * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_ATTR_MAC: MAC address (various uses)
+ * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ *	section 7.3.2.25.1, e.g. 0x000FAC04)
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_attrs {
@@ -148,6 +152,14 @@ enum nl80211_attrs {
 	/* %type: nulstring */
 	NL80211_ATTR_WIPHY_NAME,
 	NL80211_ATTR_CMDS,
+	/* %type: string */
+	NL80211_ATTR_KEY_DATA,
+	/* %type: u8 */
+	NL80211_ATTR_KEY_IDX,
+	/* %type: string/6/6/mac */
+	NL80211_ATTR_MAC,
+	/* %type: u32 */
+	NL80211_ATTR_KEY_CIPHER,
 	/* %type: u32 */
 	NL80211_ATTR_IFTYPE,
 	NL80211_ATTR_INTERFACE_LIST,
@@ -173,11 +185,6 @@ enum nl80211_attrs {
 	NL80211_ATTR_FRAG_THRESHOLD,
 	NL80211_ATTR_FLAG_SCAN_ACTIVE,
 
-	NL80211_ATTR_KEY_DATA,
-	NL80211_ATTR_KEY_ID,
-	NL80211_ATTR_KEY_TYPE,
-	NL80211_ATTR_MAC,
-	NL80211_ATTR_KEY_CIPHER,
 
 	NL80211_ATTR_BEACON_HEAD,
 	NL80211_ATTR_BEACON_TAIL,
@@ -266,20 +273,4 @@ enum nl80211_bsstype {
 };
 #define NL80211_BSSTYPE_MAX (__NL80211_BSSTYPE_AFTER_LAST - 1)
 
-/**
- * enum nl80211_keytype - key types
- * @NL80211_KEYTYPE_GROUP: group key
- * @NL80211_KEYTYPE_PAIRWISE: pairwise key
- * @NL80211_KEYTYPE_PEER: peer key
- */
-enum nl80211_keytype {
-	NL80211_KEYTYPE_GROUP,
-	NL80211_KEYTYPE_PAIRWISE,
-	NL80211_KEYTYPE_PEER,
-
-	/* keep last */
-	__NL80211_KEYTYPE_AFTER_LAST
-};
-#define NL80211_KEYTYPE_MAX (__NL80211_KEYTYPE_AFTER_LAST - 1)
-
 #endif /* __LINUX_NL80211_H */
include/net/cfg80211.h +10 -3
@@ -65,14 +65,21 @@ struct association_params {
 
 /**
  * struct key_params - key information
+ *
+ * Information about a key
+ *
+ * @key: key material
+ * @key_len: length of key material
+ * @key_idx: key index (0-3)
+ * @macaddress: MAC address (for a pairwise key) or %NULL
+ * @cipher: cipher suite selector
  */
 struct key_params {
 	u8 *key;
-	int key_len;
-	int key_id;
-	u32 key_type;
 	u8 *macaddress;
+	int key_len;
 	u32 cipher;
+	u8 key_idx;
 };
 
 
net/wireless/nl80211.c +84 -41

183 lines not on this page · raw message

net/wireless/core.c +3 -0
@@ -213,6 +213,9 @@ struct wiphy *wiphy_new(struct cfg80211_
 	drv->ops = ops;
 	drv->alive = 0;
 
+	WARN_ON(!ops->add_key && ops->del_key);
+	WARN_ON(ops->add_key && !ops->del_key);
+
 	mutex_lock(&cfg80211_drv_mutex);
 	idr_pre_get(&cfg80211_drivers, GFP_KERNEL);
 	res = idr_get_new(&cfg80211_drivers, drv, &drv->idx);
#16 lore raw

Re: [PATCH 08/15] cfg80211: clean up key add/remove interface

Johannes Berg wrote:

I found a compile problem when all the patches were installed in that 'ops' was not defined in wireless/core.c. This patch should be

+ WARN_ON(!drv->ops->add_key && drv->ops->del_key);
+ WARN_ON(drv->ops->add_key && !drv->ops->del_key);

and not WARN_ON(!ops->add_key etc.

A similar change is also required in patch 11/15.

I'm now ready to test your changes.

Larry

author maintainer
#17 lore raw

Re: [PATCH 08/15] cfg80211: clean up key add/remove interface

Quoted 9 lines · Larry Finger

I found a compile problem when all the patches were installed in that 'ops' was not defined in wireless/core.c. This patch should be

(quoted diff) +2 -0
+       WARN_ON(!drv->ops->add_key && drv->ops->del_key);
+       WARN_ON(drv->ops->add_key && !drv->ops->del_key);

and not WARN_ON(!ops->add_key etc.

A similar change is also required in patch 11/15.

Huh, odd. Seems I somehow messed up this series, I'll look into all the things next week (busy over the weekend)

johannes

author maintainer
#18 lore raw

Re: [PATCH 08/15] cfg80211: clean up key add/remove interface

In reply to Larry Finger
Quoted 9 lines · Larry Finger

Johannes Berg wrote:

I found a compile problem when all the patches were installed in that 'ops' was not defined in wireless/core.c. This patch should be

(quoted diff) +2 -0
+       WARN_ON(!drv->ops->add_key && drv->ops->del_key);
+       WARN_ON(drv->ops->add_key && !drv->ops->del_key);

and not WARN_ON(!ops->add_key etc.

I'm pretty sure this is correct since the wiphy_new prototype is

| struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)

and this is added to wiphy_new. Did the code somehow end up in the wrong place for you?

johannes

#19 lore raw

Re: [PATCH 08/15] cfg80211: clean up key add/remove interface

Quoted 10 lines · Johannes Berg
Quoted 8 lines · Larry Finger

Johannes Berg wrote:

I found a compile problem when all the patches were installed in that 'ops' was not defined in wireless/core.c. This patch should be

(quoted diff) +2 -0
+       WARN_ON(!drv->ops->add_key && drv->ops->del_key);
+       WARN_ON(drv->ops->add_key && !drv->ops->del_key);

and not WARN_ON(!ops->add_key etc.

Quoted 8 lines

I'm pretty sure this is correct since the wiphy_new prototype is

| struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)

and this is added to wiphy_new. Did the code somehow end up in the wrong place for you?

johannes

I have been working from the 'b43' branch with a top commit hash of 43a9a146a1290808519c68615809ae8bc207e8a1. It seems to be out of synch with branch 'everything' in this area.

Sorry for the noise.

Larry

author maintainer
#20 lore raw

Re: [PATCH 08/15] cfg80211: clean up key add/remove interface

Quoted 3 lines · Larry Finger

I have been working from the 'b43' branch with a top commit hash of 43a9a146a1290808519c68615809ae8bc207e8a1. It seems to be out of synch with branch 'everything' in this area.

Ah yes, that explains it, I think John grouped the cfg80211 updates with mac80211 and those aren't always pulled into the driver branches.

Quoted 1 line

Sorry for the noise.

No problem, I appreciate any bug reports.

johannes

author maintainer
#21 lore raw

PATCH 9/15 mac80211: rename ieee80211_cfg.c to cfg.c

In reply to Johannes Berg

It's just painful to have the extra ieee80211_ prefix.

---
 net/mac80211/Makefile        |    2 -
 net/mac80211/cfg.c           |   72 +++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_cfg.c |   72 -------------------------------------------
 3 files changed, 73 insertions(+), 73 deletions(-)
net/mac80211/Makefile +1 -1
@@ -17,7 +17,7 @@ mac80211-objs := \
 	regdomain.o \
 	tkip.o \
 	aes_ccm.o \
-	ieee80211_cfg.o \
+	cfg.o \
 	rx.o \
 	tx.o \
 	key.o \
net/mac80211/cfg.c new file +72 -0

72 lines not on this page · raw message

net/mac80211/ieee80211_cfg.c deleted +0 -72

72 lines not on this page · raw message

author maintainer
#22 lore raw

PATCH 10/15 mac80211: support adding/removing keys via cfg80211

In reply to Johannes Berg

This adds the necessary hooks to mac80211 to make use of the key add/remove functionality nl80211/cfg80211 offer.

---
 net/mac80211/cfg.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
net/mac80211/cfg.c +80 -0
@@ -6,6 +6,7 @@
  * This file is GPLv2 as found in COPYING.
  */
 
+#include <linux/ieee80211.h>
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <net/cfg80211.h>
@@ -66,7 +67,86 @@ static int ieee80211_del_iface(struct wi
 	return ieee80211_if_remove(local->mdev, name, -1);
 }
 
+static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+			     struct key_params *params)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta = NULL;
+	enum ieee80211_key_alg alg;
+	int ret;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	switch (params->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		alg = ALG_WEP;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		alg = ALG_TKIP;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		alg = ALG_CCMP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (params->macaddress) {
+		sta = sta_info_get(sdata->local, params->macaddress);
+		if (!sta)
+			return -EINVAL;
+
+		ieee80211_key_free(sta->key);
+	} else
+		ieee80211_key_free(sdata->keys[params->key_idx]);
+
+	ret = 0;
+	if (!ieee80211_key_alloc(sdata, sta, alg, params->key_idx,
+				 params->key_len, params->key))
+		ret = -ENOMEM;
+
+	if (sta)
+		sta_info_put(sta);
+
+	return ret;
+}
+
+static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+			     struct key_params *params)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta;
+	int ret;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (params->macaddress) {
+		sta = sta_info_get(sdata->local, params->macaddress);
+		if (!sta)
+			return -EINVAL;
+
+		ret = 0;
+		if (sta->key)
+			ieee80211_key_free(sta->key);
+		else
+			ret = -ENOENT;
+
+		sta_info_put(sta);
+		return ret;
+	}
+
+	if (!sdata->keys[params->key_idx])
+		return -ENOENT;
+
+	ieee80211_key_free(sdata->keys[params->key_idx]);
+
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
+	.add_key = ieee80211_add_key,
+	.del_key = ieee80211_del_key,
 };
author maintainer
#23 lore raw

PATCH 11/15 cfg80211: add hook for changing default key index

In reply to Johannes Berg

This introduces a new nl80211 command for setting the default key index on an interface.

---
 include/linux/nl80211.h |    3 +++
 include/net/cfg80211.h  |    3 +++
 net/wireless/core.c     |    4 ++--
 net/wireless/nl80211.c  |   41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 49 insertions(+), 2 deletions(-)
include/linux/nl80211.h +3 -0
@@ -45,6 +45,7 @@
  * @NL80211_CMD_ADD_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
  *	%NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER
  *	attributes.
+ * @NL80211_SET_DEFAULT_KEY: set the default key index
  * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
  *	or %NL80211_ATTR_MAC.
  * @__NL80211_CMD_AFTER_LAST: internal use
@@ -89,6 +90,8 @@ enum nl80211_commands {
 	NL80211_CMD_ADD_KEY,
 	/* %input: ifindex, key_idx|mac */
 	NL80211_CMD_DEL_KEY,
+	/* %input: ifindex, key_idx */
+	NL80211_CMD_SET_DEFAULT_KEY,
 
 	/* add commands here */
 
include/net/cfg80211.h +3 -0
@@ -159,6 +159,7 @@ struct wiphy;
  *		   is to be passed to that callback
  * @add_key: add a key using &struct key_params
  * @del_key: delete a key using info from &struct key_params
+ * @set_default_key: set default key index (0..3)
  */
 struct cfg80211_ops {
 	int	(*add_virtual_intf)(struct wiphy *wiphy, char *name,
@@ -188,6 +189,8 @@ struct cfg80211_ops {
 			   struct key_params *params);
 	int	(*del_key)(struct wiphy *wiphy, struct net_device *dev,
 			   struct key_params *params);
+	int	(*set_default_key)(struct wiphy *wiphy, struct net_device *dev,
+				   u8 key_idx);
 };
 
 
net/wireless/nl80211.c +41 -0

59 lines not on this page · raw message

net/wireless/core.c +2 -2
@@ -213,8 +213,8 @@ struct wiphy *wiphy_new(struct cfg80211_
 	drv->ops = ops;
 	drv->alive = 0;
 
-	WARN_ON(!ops->add_key && ops->del_key);
-	WARN_ON(ops->add_key && !ops->del_key);
+	WARN_ON(!ops->add_key && (ops->del_key || ops->set_default_key));
+	WARN_ON(ops->add_key && !(ops->del_key && ops->set_default_key));
 
 	mutex_lock(&cfg80211_drv_mutex);
 	idr_pre_get(&cfg80211_drivers, GFP_KERNEL);
author maintainer
#24 lore raw

PATCH 12/15 mac80211: support changing default key index via cfg80211

In reply to Johannes Berg

This adds the necessary hook to mac80211 so that you can change the default key index via nl80211/cfg80211.

---
 net/mac80211/cfg.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
net/mac80211/cfg.c +13 -0
@@ -144,9 +144,22 @@ static int ieee80211_del_key(struct wiph
 	return 0;
 }
 
+static int ieee80211_config_default_key(struct wiphy *wiphy,
+					struct net_device *dev,
+					u8 key_idx)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	ieee80211_set_default_key(sdata, key_idx);
+
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
 	.add_key = ieee80211_add_key,
 	.del_key = ieee80211_del_key,
+	.set_default_key = ieee80211_config_default_key,
 };
author maintainer
#25 lore raw

PATCH 13/15 mac80211: remove key threshold stuff

In reply to Johannes Berg

This patch removes the key threshold stuff from mac80211, the next patches will add it back in the form of a per-key setting that goes through nl/cfg80211.

---
 net/mac80211/debugfs.c          |    4 ----
 net/mac80211/hostapd_ioctl.h    |    1 -
 net/mac80211/ieee80211.c        |   35 -----------------------------------
 net/mac80211/ieee80211_common.h |    2 +-
 net/mac80211/ieee80211_i.h      |    7 -------
 net/mac80211/ieee80211_ioctl.c  |    8 --------
 net/mac80211/rx.c               |    7 +------
 net/mac80211/tx.c               |    7 +------
 8 files changed, 3 insertions(+), 68 deletions(-)
net/mac80211/hostapd_ioctl.h +0 -1
@@ -38,7 +38,6 @@ enum {
 	PRISM2_PARAM_PRIVACY_INVOKED = 1014,
 	PRISM2_PARAM_BROADCAST_SSID = 1015,
 	PRISM2_PARAM_EAPOL = 1023,
-	PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
 	PRISM2_PARAM_WIFI_WME_NOACK_TEST = 1033,
 	PRISM2_PARAM_SCAN_FLAGS = 1035,
 	PRISM2_PARAM_HW_MODES = 1036,
net/mac80211/ieee80211.c +0 -35
@@ -201,41 +201,6 @@ ieee80211_rx_mgmt(struct ieee80211_local
 	netif_rx(skb);
 }
 
-void ieee80211_key_threshold_notify(struct net_device *dev,
-				    struct ieee80211_key *key,
-				    struct sta_info *sta)
-{
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-	struct sk_buff *skb;
-	struct ieee80211_msg_key_notification *msg;
-
-	/* if no one will get it anyway, don't even allocate it.
-	 * unlikely because this is only relevant for APs
-	 * where the device must be open... */
-	if (unlikely(!local->apdev))
-		return;
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
-			    sizeof(struct ieee80211_msg_key_notification));
-	if (!skb)
-		return;
-
-	skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-	msg = (struct ieee80211_msg_key_notification *)
-		skb_put(skb, sizeof(struct ieee80211_msg_key_notification));
-	msg->tx_rx_count = key->tx_rx_count;
-	memcpy(msg->ifname, dev->name, IFNAMSIZ);
-	if (sta)
-		memcpy(msg->addr, sta->addr, ETH_ALEN);
-	else
-		memset(msg->addr, 0xff, ETH_ALEN);
-
-	key->tx_rx_count = 0;
-
-	ieee80211_rx_mgmt(local, skb, NULL,
-			  ieee80211_msg_key_threshold_notification);
-}
-
 static int ieee80211_mgmt_open(struct net_device *dev)
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
net/mac80211/ieee80211_common.h +1 -1
@@ -53,7 +53,7 @@ enum ieee80211_msg_type {
 	/* hole at 6, was monitor but never sent to userspace */
 	ieee80211_msg_sta_not_assoc = 7,
 	/* 8 was ieee80211_msg_set_aid_for_sta */
-	ieee80211_msg_key_threshold_notification = 9,
+	/* 9 was ieee80211_msg_key_threshold_notification */
 	/* 11 was ieee80211_msg_radar */
 };
 
net/mac80211/ieee80211_i.h +0 -7
@@ -538,9 +538,6 @@ struct ieee80211_local {
 	struct crypto_blkcipher *wep_tx_tfm;
 	struct crypto_blkcipher *wep_rx_tfm;
 	u32 wep_iv;
-	int key_tx_rx_threshold; /* number of times any key can be used in TX
-				  * or RX before generating a rekey
-				  * notification; 0 = notification disabled. */
 
 	int bridge_packets; /* bridge packets between associated stations and
 			     * deliver multicast frames both back to wireless
@@ -657,7 +654,6 @@ struct ieee80211_local {
 		struct dentry *antenna_sel_tx;
 		struct dentry *antenna_sel_rx;
 		struct dentry *bridge_packets;
-		struct dentry *key_tx_rx_threshold;
 		struct dentry *rts_threshold;
 		struct dentry *fragmentation_threshold;
 		struct dentry *short_retry_limit;
@@ -815,9 +811,6 @@ void ieee80211_if_mgmt_setup(struct net_
 struct net_device_stats *ieee80211_dev_stats(struct net_device *dev);
 struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local,
 					  int phymode, int hwrate);
-void ieee80211_key_threshold_notify(struct net_device *dev,
-				    struct ieee80211_key *key,
-				    struct sta_info *sta);
 
 /* ieee80211_ioctl.c */
 int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
net/mac80211/ieee80211_ioctl.c +0 -8
@@ -1759,10 +1759,6 @@ static int ieee80211_ioctl_prism2_param(
 		sdata->eapol = value;
 		break;
 
-	case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
-		local->key_tx_rx_threshold = value;
-		break;
-
 	case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
 		local->wifi_wme_noack_test = value;
 		break;
@@ -1885,10 +1881,6 @@ static int ieee80211_ioctl_get_prism2_pa
 		*param = sdata->eapol;
 		break;
 
-	case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
-		*param = local->key_tx_rx_threshold;
-		break;
-
 	case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
 		*param = local->wifi_wme_noack_test;
 		break;
net/mac80211/rx.c +1 -6
@@ -405,12 +405,7 @@ ieee80211_rx_h_load_key(struct ieee80211
 
 	if (rx->key && (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
 		rx->key->tx_rx_count++;
-		if (unlikely(rx->local->key_tx_rx_threshold &&
-			     rx->key->tx_rx_count >
-			     rx->local->key_tx_rx_threshold)) {
-			ieee80211_key_threshold_notify(rx->dev, rx->key,
-						       rx->sta);
-		}
+		/* TODO: add threshold stuff again */
 	}
 
 	return TXRX_CONTINUE;
net/mac80211/debugfs.c +0 -4
@@ -106,8 +106,6 @@ DEBUGFS_READONLY_FILE(antenna_sel_rx, 20
 		      local->hw.conf.antenna_sel_rx);
 DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
 		      local->bridge_packets);
-DEBUGFS_READONLY_FILE(key_tx_rx_threshold, 20, "%d",
-		      local->key_tx_rx_threshold);
 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
 		      local->rts_threshold);
 DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
@@ -333,7 +331,6 @@ void debugfs_hw_add(struct ieee80211_loc
 	DEBUGFS_ADD(antenna_sel_tx);
 	DEBUGFS_ADD(antenna_sel_rx);
 	DEBUGFS_ADD(bridge_packets);
-	DEBUGFS_ADD(key_tx_rx_threshold);
 	DEBUGFS_ADD(rts_threshold);
 	DEBUGFS_ADD(fragmentation_threshold);
 	DEBUGFS_ADD(short_retry_limit);
@@ -397,7 +394,6 @@ void debugfs_hw_del(struct ieee80211_loc
 	DEBUGFS_DEL(antenna_sel_tx);
 	DEBUGFS_DEL(antenna_sel_rx);
 	DEBUGFS_DEL(bridge_packets);
-	DEBUGFS_DEL(key_tx_rx_threshold);
 	DEBUGFS_DEL(rts_threshold);
 	DEBUGFS_DEL(fragmentation_threshold);
 	DEBUGFS_DEL(short_retry_limit);
net/mac80211/tx.c +1 -6
@@ -443,12 +443,7 @@ ieee80211_tx_h_select_key(struct ieee802
 
 	if (tx->key) {
 		tx->key->tx_rx_count++;
-		if (unlikely(tx->local->key_tx_rx_threshold &&
-			     tx->key->tx_rx_count >
-			     tx->local->key_tx_rx_threshold)) {
-			ieee80211_key_threshold_notify(tx->dev, tx->key,
-						       tx->sta);
-		}
+		/* TODO: add threshold stuff again */
 	}
 
 	return TXRX_CONTINUE;
author maintainer
#26 lore raw

PATCH 14/15 cfg80211: add key threshold stuff

In reply to Johannes Berg

This adds all requisites for key threshold setting and notification to cfg80211/nl80211.

---
 include/linux/nl80211.h |   10 +++++++++-
 include/net/cfg80211.h  |   17 +++++++++++++++++
 net/wireless/Makefile   |    2 +-
 net/wireless/nl80211.c  |   13 +++++++++++++
 net/wireless/nl80211.h  |    1 +
 net/wireless/notify.c   |   39 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 80 insertions(+), 2 deletions(-)
include/linux/nl80211.h +9 -1
@@ -48,6 +48,8 @@
  * @NL80211_SET_DEFAULT_KEY: set the default key index
  * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
  *	or %NL80211_ATTR_MAC.
+ * @NL80211_CMD_KEY_THRESHOLD_REACHED: notification from kernel that the
+ *	key threshold for a specific key has been reached.
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
 enum nl80211_commands {
@@ -86,7 +88,7 @@ enum nl80211_commands {
 	NL80211_CMD_AP_UPDATE_STA,
 	NL80211_CMD_AP_GET_STA_INFO,
 	NL80211_CMD_AP_SET_RATESETS,
-	/* %input: ifindex, key_cipher, key_data, {key_idx, mac} */
+	/* %input: ifindex, key_cipher, key_data, {key_threshold,key_idx,mac}*/
 	NL80211_CMD_ADD_KEY,
 	/* %input: ifindex, key_idx|mac */
 	NL80211_CMD_DEL_KEY,
@@ -94,6 +96,7 @@ enum nl80211_commands {
 	NL80211_CMD_SET_DEFAULT_KEY,
 
 	/* add commands here */
+	NL80211_CMD_KEY_THRESHOLD_REACHED,
 
 	/* used to define NL80211_CMD_MAX below */
 	__NL80211_CMD_AFTER_LAST
@@ -141,6 +144,8 @@ enum nl80211_commands {
  * @NL80211_ATTR_MAC: MAC address (various uses)
  * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
  *	section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_ATTR_KEY_THRESHOLD: key threshold, the kernel will generate a key
+ *	threshold notification when a key has been used this many times
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_attrs {
@@ -192,6 +197,9 @@ enum nl80211_attrs {
 	NL80211_ATTR_BEACON_HEAD,
 	NL80211_ATTR_BEACON_TAIL,
 
+	/* %type: u32 */
+	NL80211_ATTR_KEY_THRESHOLD,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	/* used to define NL80211_ATTR_MAX below */
net/wireless/nl80211.c +13 -0
@@ -103,6 +103,7 @@ static struct nla_policy nl80211_policy[
 	[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
 	[NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
 	[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
+	[NL80211_ATTR_KEY_THRESHOLD] = { .type = NLA_U32 },
 };
 
 /* netlink command implementations */
@@ -761,6 +762,10 @@ static int nl80211_add_key(struct sk_buf
 	if (info->attrs[NL80211_ATTR_MAC])
 		params.macaddress = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
+	if (info->attrs[NL80211_ATTR_KEY_THRESHOLD])
+		params.threshold =
+			nla_get_u32(info->attrs[NL80211_ATTR_KEY_THRESHOLD]);
+
 	if (params.key_idx > 3)
 		return -EINVAL;
 
@@ -1045,6 +1050,10 @@ static struct genl_multicast_group nl802
 	.name = "config",
 };
 
+struct genl_multicast_group nl80211_notify_mcgrp = {
+	.name = "notification",
+};
+
 /* notification functions */
 
 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
@@ -1088,6 +1097,10 @@ int nl80211_init(void)
 	if (err)
 		goto err_out;
 
+	err = genl_register_mc_group(&nl80211_fam, &nl80211_notify_mcgrp);
+	if (err)
+		goto err_out;
+
 	return 0;
  err_out:
 	genl_unregister_family(&nl80211_fam);
include/net/cfg80211.h +17 -0
@@ -73,12 +73,16 @@ struct association_params {
  * @key_idx: key index (0-3)
  * @macaddress: MAC address (for a pairwise key) or %NULL
  * @cipher: cipher suite selector
+ * @threshold: key threshold, notify userspace that a key has
+ *	been used this many times if possible by calling
+ *	the cfg80211_key_threshold_notify() function
  */
 struct key_params {
 	u8 *key;
 	u8 *macaddress;
 	int key_len;
 	u32 cipher;
+	u32 threshold;
 	u8 key_idx;
 };
 
@@ -193,6 +197,19 @@ struct cfg80211_ops {
 				   u8 key_idx);
 };
 
+/* notification functions */
+/**
+ * cfg80211_key_threshold_notify - notify about key threshold
+ *
+ * Use this function to notify userspace that the key threshold
+ * for a specific key has been reached.
+ *
+ * @dev: the netdevice the key is associated with
+ * @keyidx: the key index of the key
+ * @mac: the MAC address for a pairwise key or %NULL
+ */
+void cfg80211_key_threshold_notify(struct net_device *dev,
+				   u8 keyidx, u8 *mac);
 
 /* helper functions specific to nl80211 */
 extern void *nl80211hdr_put(struct sk_buff *skb, u32 pid,
net/wireless/notify.c new file +39 -0
@@ -0,0 +1,39 @@
+/*
+ * This is the new netlink-based wireless notification interface.
+ *
+ * Copyright 2007 Johannes Berg <[email protected]>
+ */
+
+#include <linux/nl80211.h>
+#include <linux/rtnetlink.h>
+#include <net/genetlink.h>
+#include <net/cfg80211.h>
+#include "core.h"
+#include "nl80211.h"
+
+void cfg80211_key_threshold_notify(struct net_device *dev,
+				   u8 keyidx, u8 *mac)
+{
+#ifdef CONFIG_NL80211
+	struct sk_buff *msg;
+	void *hdr;
+
+	hdr = nl80211msg_new(&msg, 0, 0, 0, NL80211_CMD_KEY_THRESHOLD_REACHED);
+	if (IS_ERR(hdr))
+		return;
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+	if (mac)
+		NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac);
+	NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, keyidx);
+
+	genlmsg_end(msg, hdr);
+	genlmsg_multicast(msg, 0, nl80211_notify_mcgrp.id, GFP_KERNEL);
+
+	return;
+
+ nla_put_failure:
+	nlmsg_free(msg);
+#endif
+}
+EXPORT_SYMBOL(cfg80211_key_threshold_notify);
net/wireless/Makefile +1 -1
@@ -1,5 +1,5 @@
 obj-$(CONFIG_WIRELESS_EXT) += wext.o
 obj-$(CONFIG_CFG80211) += cfg80211.o
 
-cfg80211-y += core.o sysfs.o radiotap.o
+cfg80211-y += core.o sysfs.o radiotap.o notify.o
 cfg80211-$(CONFIG_NL80211) += nl80211.o
net/wireless/nl80211.h +1 -0
@@ -7,6 +7,7 @@
 extern int nl80211_init(void);
 extern void nl80211_exit(void);
 extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
+extern struct genl_multicast_group nl80211_notify_mcgrp;
 #else
 static inline int nl80211_init(void)
 {
author maintainer
#27 lore raw

PATCH 15/15 mac80211: make use of the new cfg80211 key threshold notification

In reply to Johannes Berg

This makes mac80211 use the cfg80211 facilities for key threshold notification.

---
 net/mac80211/cfg.c             |    1 +
 net/mac80211/ieee80211_ioctl.c |    3 ++-
 net/mac80211/ieee80211_key.h   |    4 +++-
 net/mac80211/key.c             |    3 ++-
 net/mac80211/rx.c              |   10 ++++++++--
 net/mac80211/tx.c              |   17 ++++++++++++-----
 6 files changed, 28 insertions(+), 10 deletions(-)
net/mac80211/ieee80211_key.h +3 -1
@@ -86,6 +86,8 @@ struct ieee80211_key {
 
 	/* number of times this key has been used */
 	int tx_rx_count;
+	/* threshold for notification */
+	u32 tx_rx_threshold;
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct {
@@ -115,7 +117,7 @@ struct ieee80211_key {
 struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
 					  struct sta_info *sta,
 					  ieee80211_key_alg alg,
-					  int idx,
+					  int idx, u32 threshold,
 					  size_t key_len,
 					  const u8 *key_data);
 void ieee80211_key_free(struct ieee80211_key *key);
net/mac80211/key.c +2 -1
@@ -124,7 +124,7 @@ void ieee80211_key_removed(struct ieee80
 struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
 					  struct sta_info *sta,
 					  ieee80211_key_alg alg,
-					  int idx,
+					  int idx, u32 threshold,
 					  size_t key_len,
 					  const u8 *key_data)
 {
@@ -151,6 +151,7 @@ struct ieee80211_key *ieee80211_key_allo
 	key->local = sdata->local;
 	key->sdata = sdata;
 	key->sta = sta;
+	key->tx_rx_threshold = threshold;
 
 	if (alg == ALG_CCMP) {
 		/*
net/mac80211/cfg.c +1 -0
@@ -103,6 +103,7 @@ static int ieee80211_add_key(struct wiph
 
 	ret = 0;
 	if (!ieee80211_key_alloc(sdata, sta, alg, params->key_idx,
+				 params->threshold,
 				 params->key_len, params->key))
 		ret = -ENOMEM;
 
net/mac80211/ieee80211_ioctl.c +2 -1
@@ -431,7 +431,8 @@ static int ieee80211_set_encryption(stru
 		 * set_key() callback becomes confused.
 		 */
 		ieee80211_key_free(key);
-		key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
+		key = ieee80211_key_alloc(sdata, sta, alg, idx, 0,
+					  key_len, _key);
 		if (!key) {
 			ret = -ENOMEM;
 			goto err_out;
net/mac80211/rx.c +8 -2
@@ -322,6 +322,7 @@ ieee80211_rx_h_load_key(struct ieee80211
 	int keyidx;
 	int hdrlen;
 	int trying_wep = 0;
+	u8 *sta_mac = NULL;
 
 	/*
 	 * Key selection 101
@@ -401,11 +402,16 @@ ieee80211_rx_h_load_key(struct ieee80211
 			trying_wep = 1;
 			goto find_by_index;
 		}
+		sta_mac = rx->sta->addr;
 	}
 
-	if (rx->key && (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
+	if (rx->key) {
 		rx->key->tx_rx_count++;
-		/* TODO: add threshold stuff again */
+		if (rx->key->tx_rx_threshold &&
+		    rx->key->tx_rx_count > rx->key->tx_rx_threshold)
+			cfg80211_key_threshold_notify(rx->key->sdata->dev,
+						      rx->key->conf.keyidx,
+						      sta_mac);
 	}
 
 	return TXRX_CONTINUE;
net/mac80211/tx.c +12 -5
@@ -426,11 +426,14 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t
 static ieee80211_txrx_result
 ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
 {
+	u8 *sta_mac = NULL;
+
 	if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
 		tx->key = NULL;
-	else if (tx->sta && tx->sta->key)
+	else if (tx->sta && tx->sta->key) {
+		sta_mac = tx->sta->addr;
 		tx->key = tx->sta->key;
-	else if (tx->sdata->default_key)
+	} else if (tx->sdata->default_key)
 		tx->key = tx->sdata->default_key;
 	else if (tx->sdata->drop_unencrypted &&
 		 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
@@ -441,9 +444,13 @@ ieee80211_tx_h_select_key(struct ieee802
 		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
 	}
 
-	if (tx->key) {
-		tx->key->tx_rx_count++;
-		/* TODO: add threshold stuff again */
+        if (tx->key) {
+                tx->key->tx_rx_count++;
+		if (tx->key->tx_rx_threshold &&
+		    tx->key->tx_rx_count > tx->key->tx_rx_threshold)
+			cfg80211_key_threshold_notify(tx->key->sdata->dev,
+						      tx->key->conf.keyidx,
+						      sta_mac);
 	}
 
 	return TXRX_CONTINUE;
author maintainer
#28 lore raw
In reply to Johannes Berg
Quoted 2 lines · Johannes Berg

This patch series updates mac80211's and cfg80211's key handling and adds some documentation (more to follow.)

Looks like this will break the new drivers (ath5k and b43legacy)

johannes

author maintainer
#29 lore raw
In reply to Johannes Berg
Quoted 2 lines · Johannes Berg

This patch series updates mac80211's and cfg80211's key handling and adds some documentation (more to follow.)

Ok, I found the bug Larry reported, will repost tomorrow.

johannes