diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-05-25 13:42:46 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-06-03 14:10:44 -0400 |
commit | 1f03baad4d0516f4bd3a4728d71ff00b01be930d (patch) | |
tree | afecbf71bc230a3a2d0f2fa2d4bcf7b94bf278d5 | |
parent | eed8e22f0133e8278b1f8079fcb452f1f9692f9d (diff) |
ath9k: use the key handling code from ath9k_common instead of duplicating it
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 232 |
1 files changed, 2 insertions, 230 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d6e8be0999bc..120708d51d45 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -621,234 +621,6 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, | |||
621 | return chanmode; | 621 | return chanmode; |
622 | } | 622 | } |
623 | 623 | ||
624 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
625 | struct ath9k_keyval *hk, const u8 *addr, | ||
626 | bool authenticator) | ||
627 | { | ||
628 | struct ath_hw *ah = common->ah; | ||
629 | const u8 *key_rxmic; | ||
630 | const u8 *key_txmic; | ||
631 | |||
632 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
633 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
634 | |||
635 | if (addr == NULL) { | ||
636 | /* | ||
637 | * Group key installation - only two key cache entries are used | ||
638 | * regardless of splitmic capability since group key is only | ||
639 | * used either for TX or RX. | ||
640 | */ | ||
641 | if (authenticator) { | ||
642 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
643 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
644 | } else { | ||
645 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
646 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
647 | } | ||
648 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
649 | } | ||
650 | if (!common->splitmic) { | ||
651 | /* TX and RX keys share the same key cache entry. */ | ||
652 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
653 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
654 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
655 | } | ||
656 | |||
657 | /* Separate key cache entries for TX and RX */ | ||
658 | |||
659 | /* TX key goes at first index, RX key at +32. */ | ||
660 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
661 | if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { | ||
662 | /* TX MIC entry failed. No need to proceed further */ | ||
663 | ath_print(common, ATH_DBG_FATAL, | ||
664 | "Setting TX MIC Key Failed\n"); | ||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
669 | /* XXX delete tx key on failure? */ | ||
670 | return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); | ||
671 | } | ||
672 | |||
673 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
674 | { | ||
675 | int i; | ||
676 | |||
677 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
678 | if (test_bit(i, common->keymap) || | ||
679 | test_bit(i + 64, common->keymap)) | ||
680 | continue; /* At least one part of TKIP key allocated */ | ||
681 | if (common->splitmic && | ||
682 | (test_bit(i + 32, common->keymap) || | ||
683 | test_bit(i + 64 + 32, common->keymap))) | ||
684 | continue; /* At least one part of TKIP key allocated */ | ||
685 | |||
686 | /* Found a free slot for a TKIP key */ | ||
687 | return i; | ||
688 | } | ||
689 | return -1; | ||
690 | } | ||
691 | |||
692 | static int ath_reserve_key_cache_slot(struct ath_common *common) | ||
693 | { | ||
694 | int i; | ||
695 | |||
696 | /* First, try to find slots that would not be available for TKIP. */ | ||
697 | if (common->splitmic) { | ||
698 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
699 | if (!test_bit(i, common->keymap) && | ||
700 | (test_bit(i + 32, common->keymap) || | ||
701 | test_bit(i + 64, common->keymap) || | ||
702 | test_bit(i + 64 + 32, common->keymap))) | ||
703 | return i; | ||
704 | if (!test_bit(i + 32, common->keymap) && | ||
705 | (test_bit(i, common->keymap) || | ||
706 | test_bit(i + 64, common->keymap) || | ||
707 | test_bit(i + 64 + 32, common->keymap))) | ||
708 | return i + 32; | ||
709 | if (!test_bit(i + 64, common->keymap) && | ||
710 | (test_bit(i , common->keymap) || | ||
711 | test_bit(i + 32, common->keymap) || | ||
712 | test_bit(i + 64 + 32, common->keymap))) | ||
713 | return i + 64; | ||
714 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
715 | (test_bit(i, common->keymap) || | ||
716 | test_bit(i + 32, common->keymap) || | ||
717 | test_bit(i + 64, common->keymap))) | ||
718 | return i + 64 + 32; | ||
719 | } | ||
720 | } else { | ||
721 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
722 | if (!test_bit(i, common->keymap) && | ||
723 | test_bit(i + 64, common->keymap)) | ||
724 | return i; | ||
725 | if (test_bit(i, common->keymap) && | ||
726 | !test_bit(i + 64, common->keymap)) | ||
727 | return i + 64; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | /* No partially used TKIP slots, pick any available slot */ | ||
732 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
733 | /* Do not allow slots that could be needed for TKIP group keys | ||
734 | * to be used. This limitation could be removed if we know that | ||
735 | * TKIP will not be used. */ | ||
736 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
737 | continue; | ||
738 | if (common->splitmic) { | ||
739 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
740 | continue; | ||
741 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
742 | continue; | ||
743 | } | ||
744 | |||
745 | if (!test_bit(i, common->keymap)) | ||
746 | return i; /* Found a free slot for a key */ | ||
747 | } | ||
748 | |||
749 | /* No free slot found */ | ||
750 | return -1; | ||
751 | } | ||
752 | |||
753 | static int ath_key_config(struct ath_common *common, | ||
754 | struct ieee80211_vif *vif, | ||
755 | struct ieee80211_sta *sta, | ||
756 | struct ieee80211_key_conf *key) | ||
757 | { | ||
758 | struct ath_hw *ah = common->ah; | ||
759 | struct ath9k_keyval hk; | ||
760 | const u8 *mac = NULL; | ||
761 | int ret = 0; | ||
762 | int idx; | ||
763 | |||
764 | memset(&hk, 0, sizeof(hk)); | ||
765 | |||
766 | switch (key->alg) { | ||
767 | case ALG_WEP: | ||
768 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
769 | break; | ||
770 | case ALG_TKIP: | ||
771 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
772 | break; | ||
773 | case ALG_CCMP: | ||
774 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
775 | break; | ||
776 | default: | ||
777 | return -EOPNOTSUPP; | ||
778 | } | ||
779 | |||
780 | hk.kv_len = key->keylen; | ||
781 | memcpy(hk.kv_val, key->key, key->keylen); | ||
782 | |||
783 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
784 | /* For now, use the default keys for broadcast keys. This may | ||
785 | * need to change with virtual interfaces. */ | ||
786 | idx = key->keyidx; | ||
787 | } else if (key->keyidx) { | ||
788 | if (WARN_ON(!sta)) | ||
789 | return -EOPNOTSUPP; | ||
790 | mac = sta->addr; | ||
791 | |||
792 | if (vif->type != NL80211_IFTYPE_AP) { | ||
793 | /* Only keyidx 0 should be used with unicast key, but | ||
794 | * allow this for client mode for now. */ | ||
795 | idx = key->keyidx; | ||
796 | } else | ||
797 | return -EIO; | ||
798 | } else { | ||
799 | if (WARN_ON(!sta)) | ||
800 | return -EOPNOTSUPP; | ||
801 | mac = sta->addr; | ||
802 | |||
803 | if (key->alg == ALG_TKIP) | ||
804 | idx = ath_reserve_key_cache_slot_tkip(common); | ||
805 | else | ||
806 | idx = ath_reserve_key_cache_slot(common); | ||
807 | if (idx < 0) | ||
808 | return -ENOSPC; /* no free key cache entries */ | ||
809 | } | ||
810 | |||
811 | if (key->alg == ALG_TKIP) | ||
812 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
813 | vif->type == NL80211_IFTYPE_AP); | ||
814 | else | ||
815 | ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); | ||
816 | |||
817 | if (!ret) | ||
818 | return -EIO; | ||
819 | |||
820 | set_bit(idx, common->keymap); | ||
821 | if (key->alg == ALG_TKIP) { | ||
822 | set_bit(idx + 64, common->keymap); | ||
823 | if (common->splitmic) { | ||
824 | set_bit(idx + 32, common->keymap); | ||
825 | set_bit(idx + 64 + 32, common->keymap); | ||
826 | } | ||
827 | } | ||
828 | |||
829 | return idx; | ||
830 | } | ||
831 | |||
832 | static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key) | ||
833 | { | ||
834 | struct ath_hw *ah = common->ah; | ||
835 | |||
836 | ath9k_hw_keyreset(ah, key->hw_key_idx); | ||
837 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
838 | return; | ||
839 | |||
840 | clear_bit(key->hw_key_idx, common->keymap); | ||
841 | if (key->alg != ALG_TKIP) | ||
842 | return; | ||
843 | |||
844 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
845 | if (common->splitmic) { | ||
846 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
847 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
848 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
849 | } | ||
850 | } | ||
851 | |||
852 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 624 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
853 | struct ieee80211_vif *vif, | 625 | struct ieee80211_vif *vif, |
854 | struct ieee80211_bss_conf *bss_conf) | 626 | struct ieee80211_bss_conf *bss_conf) |
@@ -1813,7 +1585,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1813 | 1585 | ||
1814 | switch (cmd) { | 1586 | switch (cmd) { |
1815 | case SET_KEY: | 1587 | case SET_KEY: |
1816 | ret = ath_key_config(common, vif, sta, key); | 1588 | ret = ath9k_cmn_key_config(common, vif, sta, key); |
1817 | if (ret >= 0) { | 1589 | if (ret >= 0) { |
1818 | key->hw_key_idx = ret; | 1590 | key->hw_key_idx = ret; |
1819 | /* push IV and Michael MIC generation to stack */ | 1591 | /* push IV and Michael MIC generation to stack */ |
@@ -1826,7 +1598,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1826 | } | 1598 | } |
1827 | break; | 1599 | break; |
1828 | case DISABLE_KEY: | 1600 | case DISABLE_KEY: |
1829 | ath_key_delete(common, key); | 1601 | ath9k_cmn_key_delete(common, key); |
1830 | break; | 1602 | break; |
1831 | default: | 1603 | default: |
1832 | ret = -EINVAL; | 1604 | ret = -EINVAL; |