All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/2] more crypto access for drivers
@ 2011-07-06 12:12 Johannes Berg
  2011-07-06 12:12 ` [RFC 1/2] mac80211: allow drivers to access key sequence counter Johannes Berg
  2011-07-06 12:12 ` [RFC 2/2] mac80211: allow driver to generate P1K for IV32 Johannes Berg
  0 siblings, 2 replies; 4+ messages in thread
From: Johannes Berg @ 2011-07-06 12:12 UTC (permalink / raw)
  To: linux-wireless

I need these for WoWLAN GTK rekeying in the device -- comments?

I haven't implemented the wakeup part yet, we might not even
be able to and may have to reconnect on resume, still checking.

johannes


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 1/2] mac80211: allow drivers to access key sequence counter
  2011-07-06 12:12 [RFC 0/2] more crypto access for drivers Johannes Berg
@ 2011-07-06 12:12 ` Johannes Berg
  2011-07-06 14:33   ` Johannes Berg
  2011-07-06 12:12 ` [RFC 2/2] mac80211: allow driver to generate P1K for IV32 Johannes Berg
  1 sibling, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2011-07-06 12:12 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

In order to implement GTK rekeying, the device
needs to be able to encrypt frames with the
right PN/IV.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h |   58 ++++++++++++++++++++++++++++++++++++++++
 net/mac80211/key.c     |   70 +++++++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/key.h     |    7 ++--
 3 files changed, 132 insertions(+), 3 deletions(-)

--- a/include/net/mac80211.h	2011-07-06 12:45:34.000000000 +0200
+++ b/include/net/mac80211.h	2011-07-06 12:45:35.000000000 +0200
@@ -2592,6 +2592,64 @@ void ieee80211_get_tkip_p2k(struct ieee8
 			    struct sk_buff *skb, u8 *p2k);
 
 /**
+ * struct ieee80211_key_seq - key sequence counter
+ *
+ * @tkip: TKIP data, containing IV32 and IV16 in host byte order
+ * @ccmp: PN data, most significant byte first (big endian,
+ *	reverse order than in packet)
+ * @aes_cmac: PN data, most significant byte first (big endian,
+ *	reverse order than in packet)
+ */
+struct ieee80211_key_seq {
+	union {
+		struct {
+			u32 iv32;
+			u16 iv16;
+		} tkip;
+		struct {
+			u8 pn[6];
+		} ccmp;
+		struct {
+			u8 pn[6];
+		} aes_cmac;
+	};
+};
+
+/**
+ * ieee80211_get_key_tx_seq - get key TX sequence counter
+ *
+ * @keyconf: the parameter passed with the set key
+ * @seq: buffer to receive the sequence data
+ *
+ * This function allows a driver to retrieve the current TX IV/PN
+ * for the given key. It must not be called if IV generation is
+ * offloaded to the device.
+ *
+ * Note that this function may only be called when no TX processing
+ * can be done concurrently, for example when queues are stopped
+ * and the stop has been synchronized.
+ */
+void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
+			      struct ieee80211_key_seq *seq);
+
+/**
+ * ieee80211_get_key_rx_seq - get key RX sequence counter
+ *
+ * @keyconf: the parameter passed with the set key
+ * @tid: the TID, or -1 for the non-QoS value
+ * @seq: buffer to receive the sequence data
+ *
+ * This function allows a driver to retrieve the current RX IV/PNs
+ * for the given key. It must not be called if IV checking is done
+ * by the device and not by mac80211.
+ *
+ * Note that this function may only be called when no RX processing
+ * can be done concurrently.
+ */
+void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
+			      s8 tid, struct ieee80211_key_seq *seq);
+
+/**
  * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
  * @vif: virtual interface the rekeying was done on
  * @bssid: The BSSID of the AP, for checking association
--- a/net/mac80211/key.c	2011-07-06 12:45:34.000000000 +0200
+++ b/net/mac80211/key.c	2011-07-06 12:45:35.000000000 +0200
@@ -579,3 +579,73 @@ void ieee80211_gtk_rekey_notify(struct i
 	cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
 }
 EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
+
+void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
+			      struct ieee80211_key_seq *seq)
+{
+	struct ieee80211_key *key;
+	u64 pn64;
+
+	if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+		return;
+
+	key = container_of(keyconf, struct ieee80211_key, conf);
+
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		seq->tkip.iv32 = key->u.tkip.tx.iv32;
+		seq->tkip.iv16 = key->u.tkip.tx.iv16;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
+		seq->ccmp.pn[5] = pn64;
+		seq->ccmp.pn[4] = pn64 >> 8;
+		seq->ccmp.pn[3] = pn64 >> 16;
+		seq->ccmp.pn[2] = pn64 >> 24;
+		seq->ccmp.pn[1] = pn64 >> 32;
+		seq->ccmp.pn[0] = pn64 >> 40;
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		memcpy(seq->aes_cmac.pn, key->u.aes_cmac.tx_pn, CMAC_PN_LEN);
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+EXPORT_SYMBOL(ieee80211_get_key_tx_seq);
+
+void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
+			      s8 tid, struct ieee80211_key_seq *seq)
+{
+	struct ieee80211_key *key;
+	const u8 *pn;
+
+	if (WARN_ON(tid < -1 || tid > 15))
+		return;
+
+	key = container_of(keyconf, struct ieee80211_key, conf);
+
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		if (tid < 0) {
+			seq->tkip.iv32 = key->u.tkip.rx[16].iv32;
+			seq->tkip.iv16 = key->u.tkip.rx[16].iv16;
+		} else {
+			seq->tkip.iv32 = key->u.tkip.rx[tid].iv32;
+			seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
+		}
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		if (tid < 0)
+			pn = key->u.ccmp.rx_pn[16];
+		else
+			pn = key->u.ccmp.rx_pn[tid];
+		memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		pn = key->u.aes_cmac.rx_pn;
+		memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
+		break;
+	}
+}
+EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
--- a/net/mac80211/key.h	2011-07-06 12:45:35.000000000 +0200
+++ b/net/mac80211/key.h	2011-07-06 12:45:35.000000000 +0200
@@ -28,6 +28,7 @@
 #define CCMP_PN_LEN		6
 #define TKIP_IV_LEN		8
 #define TKIP_ICV_LEN		4
+#define CMAC_PN_LEN		6
 
 #define NUM_RX_DATA_QUEUES	17
 
@@ -89,7 +90,7 @@ struct ieee80211_key {
 			 * frames and the last counter is used with Robust
 			 * Management frames.
 			 */
-			u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6];
+			u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCCMPReplays */
 			/* scratch buffers for virt_to_page() (crypto API) */
@@ -100,8 +101,8 @@ struct ieee80211_key {
 			u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
 		} ccmp;
 		struct {
-			u8 tx_pn[6];
-			u8 rx_pn[6];
+			u8 tx_pn[CMAC_PN_LEN];
+			u8 rx_pn[CMAC_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCMACReplays */
 			u32 icverrors; /* dot11RSNAStatsCMACICVErrors */



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 2/2] mac80211: allow driver to generate P1K for IV32
  2011-07-06 12:12 [RFC 0/2] more crypto access for drivers Johannes Berg
  2011-07-06 12:12 ` [RFC 1/2] mac80211: allow drivers to access key sequence counter Johannes Berg
@ 2011-07-06 12:12 ` Johannes Berg
  1 sibling, 0 replies; 4+ messages in thread
From: Johannes Berg @ 2011-07-06 12:12 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

In order to support pre-populating the P1K cache in
iwlwifi hardware for WoWLAN, we need to calculate
the P1K for the current IV32. Allow drivers to get
the P1K for any given IV32 instead of for a given
packet, but keep the packet-based version around as
an inline.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
This should also enable fixing b43's code -- it's
also pre-populating the cache in normal operation.

 include/net/mac80211.h |   24 ++++++++++++++++++++++--
 net/mac80211/tkip.c    |    9 +++------
 2 files changed, 25 insertions(+), 8 deletions(-)

--- a/include/net/mac80211.h	2011-07-06 12:45:35.000000000 +0200
+++ b/include/net/mac80211.h	2011-07-06 12:45:55.000000000 +0200
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
+#include <asm/unaligned.h>
 
 /**
  * DOC: Introduction
@@ -2564,6 +2565,18 @@ struct sk_buff *
 ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 
 /**
+ * ieee80211_get_tkip_p1k_iv - get a TKIP phase 1 key for IV32
+ *
+ * This function returns the TKIP phase 1 key for the given IV32.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @iv32: IV32 to get the P1K for
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
+			       u32 iv32, u16 *p1k);
+
+/**
  * ieee80211_get_tkip_p1k - get a TKIP phase 1 key
  *
  * This function returns the TKIP phase 1 key for the IV32 taken
@@ -2574,8 +2587,15 @@ ieee80211_get_buffered_bc(struct ieee802
  *	with this P1K
  * @p1k: a buffer to which the key will be written, as 5 u16 values
  */
-void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
-			    struct sk_buff *skb, u16 *p1k);
+static inline void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
+					  struct sk_buff *skb, u16 *p1k)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
+	u32 iv32 = get_unaligned_le32(&data[4]);
+
+	ieee80211_get_tkip_p1k_iv(keyconf, iv32, p1k);
+}
 
 /**
  * ieee80211_get_tkip_p2k - get a TKIP phase 2 key
--- a/net/mac80211/tkip.c	2011-07-06 12:45:34.000000000 +0200
+++ b/net/mac80211/tkip.c	2011-07-06 13:30:50.000000000 +0200
@@ -170,15 +170,12 @@ static void ieee80211_compute_tkip_p1k(s
 		tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32);
 }
 
-void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
-			    struct sk_buff *skb, u16 *p1k)
+void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
+			       u32 iv32, u16 *p1k)
 {
 	struct ieee80211_key *key = (struct ieee80211_key *)
 			container_of(keyconf, struct ieee80211_key, conf);
 	struct tkip_ctx *ctx = &key->u.tkip.tx;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-	u32 iv32 = get_unaligned_le32(&data[4]);
 	unsigned long flags;
 
 	spin_lock_irqsave(&key->u.tkip.txlock, flags);
@@ -186,7 +183,7 @@ void ieee80211_get_tkip_p1k(struct ieee8
 	memcpy(p1k, ctx->p1k, sizeof(ctx->p1k));
 	spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
 }
-EXPORT_SYMBOL(ieee80211_get_tkip_p1k);
+EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv);
 
 void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
 			    struct sk_buff *skb, u8 *p2k)



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC 1/2] mac80211: allow drivers to access key sequence counter
  2011-07-06 12:12 ` [RFC 1/2] mac80211: allow drivers to access key sequence counter Johannes Berg
@ 2011-07-06 14:33   ` Johannes Berg
  0 siblings, 0 replies; 4+ messages in thread
From: Johannes Berg @ 2011-07-06 14:33 UTC (permalink / raw)
  To: linux-wireless

On Wed, 2011-07-06 at 14:12 +0200, Johannes Berg wrote:

> +/**
> + * ieee80211_get_key_rx_seq - get key RX sequence counter
> + *
> + * @keyconf: the parameter passed with the set key
> + * @tid: the TID, or -1 for the non-QoS value

This is of course wrong. The -1 should be for *management* frames. I'll
fix that for the real submission.

johannes


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-07-06 14:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-06 12:12 [RFC 0/2] more crypto access for drivers Johannes Berg
2011-07-06 12:12 ` [RFC 1/2] mac80211: allow drivers to access key sequence counter Johannes Berg
2011-07-06 14:33   ` Johannes Berg
2011-07-06 12:12 ` [RFC 2/2] mac80211: allow driver to generate P1K for IV32 Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.