diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-07-07 12:58:00 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-07-08 11:42:22 -0400 |
commit | 3ea542d3c2862142ae511fac5ce2dfc7419dcc53 (patch) | |
tree | 472807c6d2a0aefa050a63cc34d9e2a2f7a3f2a6 /net/mac80211/key.c | |
parent | 9e26297a56453315ae6829aec609b5a6309af7b4 (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>
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r-- | net/mac80211/key.c | 74 |
1 files changed, 74 insertions, 0 deletions
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 | } |
628 | EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); | 628 | EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); |
629 | |||
630 | void 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 | } | ||
668 | EXPORT_SYMBOL(ieee80211_get_key_tx_seq); | ||
669 | |||
670 | void 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 | } | ||
702 | EXPORT_SYMBOL(ieee80211_get_key_rx_seq); | ||