aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-07 12:58:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-08 11:42:22 -0400
commit3ea542d3c2862142ae511fac5ce2dfc7419dcc53 (patch)
tree472807c6d2a0aefa050a63cc34d9e2a2f7a3f2a6
parent9e26297a56453315ae6829aec609b5a6309af7b4 (diff)
mac80211: allow drivers to access key sequence counter
In order to implement GTK rekeying, the device needs to be able to encrypt frames with the right PN/IV and check the PN/IV in RX frames. To be able to tell it about all those counters, we need to be able to get them from mac80211, this adds the required API. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h60
-rw-r--r--net/mac80211/key.c74
-rw-r--r--net/mac80211/key.h5
3 files changed, 137 insertions, 2 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0aae7bc1eeae..84770cedae2d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2592,6 +2592,66 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
2592 struct sk_buff *skb, u8 *p2k); 2592 struct sk_buff *skb, u8 *p2k);
2593 2593
2594/** 2594/**
2595 * struct ieee80211_key_seq - key sequence counter
2596 *
2597 * @tkip: TKIP data, containing IV32 and IV16 in host byte order
2598 * @ccmp: PN data, most significant byte first (big endian,
2599 * reverse order than in packet)
2600 * @aes_cmac: PN data, most significant byte first (big endian,
2601 * reverse order than in packet)
2602 */
2603struct ieee80211_key_seq {
2604 union {
2605 struct {
2606 u32 iv32;
2607 u16 iv16;
2608 } tkip;
2609 struct {
2610 u8 pn[6];
2611 } ccmp;
2612 struct {
2613 u8 pn[6];
2614 } aes_cmac;
2615 };
2616};
2617
2618/**
2619 * ieee80211_get_key_tx_seq - get key TX sequence counter
2620 *
2621 * @keyconf: the parameter passed with the set key
2622 * @seq: buffer to receive the sequence data
2623 *
2624 * This function allows a driver to retrieve the current TX IV/PN
2625 * for the given key. It must not be called if IV generation is
2626 * offloaded to the device.
2627 *
2628 * Note that this function may only be called when no TX processing
2629 * can be done concurrently, for example when queues are stopped
2630 * and the stop has been synchronized.
2631 */
2632void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
2633 struct ieee80211_key_seq *seq);
2634
2635/**
2636 * ieee80211_get_key_rx_seq - get key RX sequence counter
2637 *
2638 * @keyconf: the parameter passed with the set key
2639 * @tid: The TID, or -1 for the management frame value (CCMP only);
2640 * the value on TID 0 is also used for non-QoS frames. For
2641 * CMAC, only TID 0 is valid.
2642 * @seq: buffer to receive the sequence data
2643 *
2644 * This function allows a driver to retrieve the current RX IV/PNs
2645 * for the given key. It must not be called if IV checking is done
2646 * by the device and not by mac80211.
2647 *
2648 * Note that this function may only be called when no RX processing
2649 * can be done concurrently.
2650 */
2651void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
2652 int tid, struct ieee80211_key_seq *seq);
2653
2654/**
2595 * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying 2655 * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
2596 * @vif: virtual interface the rekeying was done on 2656 * @vif: virtual interface the rekeying was done on
2597 * @bssid: The BSSID of the AP, for checking association 2657 * @bssid: The BSSID of the AP, for checking association
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index d930d4d4876d..739bee13e813 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -626,3 +626,77 @@ void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
626 cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp); 626 cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
627} 627}
628EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); 628EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
629
630void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
631 struct ieee80211_key_seq *seq)
632{
633 struct ieee80211_key *key;
634 u64 pn64;
635
636 if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
637 return;
638
639 key = container_of(keyconf, struct ieee80211_key, conf);
640
641 switch (key->conf.cipher) {
642 case WLAN_CIPHER_SUITE_TKIP:
643 seq->tkip.iv32 = key->u.tkip.tx.iv32;
644 seq->tkip.iv16 = key->u.tkip.tx.iv16;
645 break;
646 case WLAN_CIPHER_SUITE_CCMP:
647 pn64 = atomic64_read(&key->u.ccmp.tx_pn);
648 seq->ccmp.pn[5] = pn64;
649 seq->ccmp.pn[4] = pn64 >> 8;
650 seq->ccmp.pn[3] = pn64 >> 16;
651 seq->ccmp.pn[2] = pn64 >> 24;
652 seq->ccmp.pn[1] = pn64 >> 32;
653 seq->ccmp.pn[0] = pn64 >> 40;
654 break;
655 case WLAN_CIPHER_SUITE_AES_CMAC:
656 pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
657 seq->ccmp.pn[5] = pn64;
658 seq->ccmp.pn[4] = pn64 >> 8;
659 seq->ccmp.pn[3] = pn64 >> 16;
660 seq->ccmp.pn[2] = pn64 >> 24;
661 seq->ccmp.pn[1] = pn64 >> 32;
662 seq->ccmp.pn[0] = pn64 >> 40;
663 break;
664 default:
665 WARN_ON(1);
666 }
667}
668EXPORT_SYMBOL(ieee80211_get_key_tx_seq);
669
670void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
671 int tid, struct ieee80211_key_seq *seq)
672{
673 struct ieee80211_key *key;
674 const u8 *pn;
675
676 key = container_of(keyconf, struct ieee80211_key, conf);
677
678 switch (key->conf.cipher) {
679 case WLAN_CIPHER_SUITE_TKIP:
680 if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES))
681 return;
682 seq->tkip.iv32 = key->u.tkip.rx[tid].iv32;
683 seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
684 break;
685 case WLAN_CIPHER_SUITE_CCMP:
686 if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES))
687 return;
688 if (tid < 0)
689 pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES];
690 else
691 pn = key->u.ccmp.rx_pn[tid];
692 memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
693 break;
694 case WLAN_CIPHER_SUITE_AES_CMAC:
695 if (WARN_ON(tid != 0))
696 return;
697 pn = key->u.aes_cmac.rx_pn;
698 memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
699 break;
700 }
701}
702EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index beb9c20ff48c..86b216b01415 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -28,6 +28,7 @@
28#define CCMP_PN_LEN 6 28#define CCMP_PN_LEN 6
29#define TKIP_IV_LEN 8 29#define TKIP_IV_LEN 8
30#define TKIP_ICV_LEN 4 30#define TKIP_ICV_LEN 4
31#define CMAC_PN_LEN 6
31 32
32#define NUM_RX_DATA_QUEUES 16 33#define NUM_RX_DATA_QUEUES 16
33 34
@@ -89,13 +90,13 @@ struct ieee80211_key {
89 * frames and the last counter is used with Robust 90 * frames and the last counter is used with Robust
90 * Management frames. 91 * Management frames.
91 */ 92 */
92 u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6]; 93 u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN];
93 struct crypto_cipher *tfm; 94 struct crypto_cipher *tfm;
94 u32 replays; /* dot11RSNAStatsCCMPReplays */ 95 u32 replays; /* dot11RSNAStatsCCMPReplays */
95 } ccmp; 96 } ccmp;
96 struct { 97 struct {
97 atomic64_t tx_pn; 98 atomic64_t tx_pn;
98 u8 rx_pn[6]; 99 u8 rx_pn[CMAC_PN_LEN];
99 struct crypto_cipher *tfm; 100 struct crypto_cipher *tfm;
100 u32 replays; /* dot11RSNAStatsCMACReplays */ 101 u32 replays; /* dot11RSNAStatsCMACReplays */
101 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 102 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */