summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h83
-rw-r--r--net/mac80211/key.c154
-rw-r--r--net/mac80211/util.c2
3 files changed, 231 insertions, 8 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index df93c77c97ab..e3e303778936 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3688,6 +3688,89 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
3688 int tid, struct ieee80211_key_seq *seq); 3688 int tid, struct ieee80211_key_seq *seq);
3689 3689
3690/** 3690/**
3691 * ieee80211_set_key_tx_seq - set key TX sequence counter
3692 *
3693 * @keyconf: the parameter passed with the set key
3694 * @seq: new sequence data
3695 *
3696 * This function allows a driver to set the current TX IV/PNs for the
3697 * given key. This is useful when resuming from WoWLAN sleep and the
3698 * device may have transmitted frames using the PTK, e.g. replies to
3699 * ARP requests.
3700 *
3701 * Note that this function may only be called when no TX processing
3702 * can be done concurrently.
3703 */
3704void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
3705 struct ieee80211_key_seq *seq);
3706
3707/**
3708 * ieee80211_set_key_rx_seq - set key RX sequence counter
3709 *
3710 * @keyconf: the parameter passed with the set key
3711 * @tid: The TID, or -1 for the management frame value (CCMP only);
3712 * the value on TID 0 is also used for non-QoS frames. For
3713 * CMAC, only TID 0 is valid.
3714 * @seq: new sequence data
3715 *
3716 * This function allows a driver to set the current RX IV/PNs for the
3717 * given key. This is useful when resuming from WoWLAN sleep and GTK
3718 * rekey may have been done while suspended. It should not be called
3719 * if IV checking is done by the device and not by mac80211.
3720 *
3721 * Note that this function may only be called when no RX processing
3722 * can be done concurrently.
3723 */
3724void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
3725 int tid, struct ieee80211_key_seq *seq);
3726
3727/**
3728 * ieee80211_remove_key - remove the given key
3729 * @keyconf: the parameter passed with the set key
3730 *
3731 * Remove the given key. If the key was uploaded to the hardware at the
3732 * time this function is called, it is not deleted in the hardware but
3733 * instead assumed to have been removed already.
3734 *
3735 * Note that due to locking considerations this function can (currently)
3736 * only be called during key iteration (ieee80211_iter_keys().)
3737 */
3738void ieee80211_remove_key(struct ieee80211_key_conf *keyconf);
3739
3740/**
3741 * ieee80211_gtk_rekey_add - add a GTK key from rekeying during WoWLAN
3742 * @vif: the virtual interface to add the key on
3743 * @keyconf: new key data
3744 *
3745 * When GTK rekeying was done while the system was suspended, (a) new
3746 * key(s) will be available. These will be needed by mac80211 for proper
3747 * RX processing, so this function allows setting them.
3748 *
3749 * The function returns the newly allocated key structure, which will
3750 * have similar contents to the passed key configuration but point to
3751 * mac80211-owned memory. In case of errors, the function returns an
3752 * ERR_PTR(), use IS_ERR() etc.
3753 *
3754 * Note that this function assumes the key isn't added to hardware
3755 * acceleration, so no TX will be done with the key. Since it's a GTK
3756 * on managed (station) networks, this is true anyway. If the driver
3757 * calls this function from the resume callback and subsequently uses
3758 * the return code 1 to reconfigure the device, this key will be part
3759 * of the reconfiguration.
3760 *
3761 * Note that the driver should also call ieee80211_set_key_rx_seq()
3762 * for the new key for each TID to set up sequence counters properly.
3763 *
3764 * IMPORTANT: If this replaces a key that is present in the hardware,
3765 * then it will attempt to remove it during this call. In many cases
3766 * this isn't what you want, so call ieee80211_remove_key() first for
3767 * the key that's being replaced.
3768 */
3769struct ieee80211_key_conf *
3770ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
3771 struct ieee80211_key_conf *keyconf);
3772
3773/**
3691 * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying 3774 * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
3692 * @vif: virtual interface the rekeying was done on 3775 * @vif: virtual interface the rekeying was done on
3693 * @bssid: The BSSID of the AP, for checking association 3776 * @bssid: The BSSID of the AP, for checking association
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index e39cc91d0cf1..620677e897bd 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -93,6 +93,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
93 93
94 might_sleep(); 94 might_sleep();
95 95
96 if (key->flags & KEY_FLAG_TAINTED)
97 return -EINVAL;
98
96 if (!key->local->ops->set_key) 99 if (!key->local->ops->set_key)
97 goto out_unsupported; 100 goto out_unsupported;
98 101
@@ -455,6 +458,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
455 struct ieee80211_sub_if_data *sdata, 458 struct ieee80211_sub_if_data *sdata,
456 struct sta_info *sta) 459 struct sta_info *sta)
457{ 460{
461 struct ieee80211_local *local = sdata->local;
458 struct ieee80211_key *old_key; 462 struct ieee80211_key *old_key;
459 int idx, ret; 463 int idx, ret;
460 bool pairwise; 464 bool pairwise;
@@ -484,10 +488,13 @@ int ieee80211_key_link(struct ieee80211_key *key,
484 488
485 ieee80211_debugfs_key_add(key); 489 ieee80211_debugfs_key_add(key);
486 490
487 ret = ieee80211_key_enable_hw_accel(key); 491 if (!local->wowlan) {
488 492 ret = ieee80211_key_enable_hw_accel(key);
489 if (ret) 493 if (ret)
490 ieee80211_key_free(key, true); 494 ieee80211_key_free(key, true);
495 } else {
496 ret = 0;
497 }
491 498
492 mutex_unlock(&sdata->local->key_mtx); 499 mutex_unlock(&sdata->local->key_mtx);
493 500
@@ -540,7 +547,7 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
540 void *iter_data) 547 void *iter_data)
541{ 548{
542 struct ieee80211_local *local = hw_to_local(hw); 549 struct ieee80211_local *local = hw_to_local(hw);
543 struct ieee80211_key *key; 550 struct ieee80211_key *key, *tmp;
544 struct ieee80211_sub_if_data *sdata; 551 struct ieee80211_sub_if_data *sdata;
545 552
546 ASSERT_RTNL(); 553 ASSERT_RTNL();
@@ -548,13 +555,14 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
548 mutex_lock(&local->key_mtx); 555 mutex_lock(&local->key_mtx);
549 if (vif) { 556 if (vif) {
550 sdata = vif_to_sdata(vif); 557 sdata = vif_to_sdata(vif);
551 list_for_each_entry(key, &sdata->key_list, list) 558 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
552 iter(hw, &sdata->vif, 559 iter(hw, &sdata->vif,
553 key->sta ? &key->sta->sta : NULL, 560 key->sta ? &key->sta->sta : NULL,
554 &key->conf, iter_data); 561 &key->conf, iter_data);
555 } else { 562 } else {
556 list_for_each_entry(sdata, &local->interfaces, list) 563 list_for_each_entry(sdata, &local->interfaces, list)
557 list_for_each_entry(key, &sdata->key_list, list) 564 list_for_each_entry_safe(key, tmp,
565 &sdata->key_list, list)
558 iter(hw, &sdata->vif, 566 iter(hw, &sdata->vif,
559 key->sta ? &key->sta->sta : NULL, 567 key->sta ? &key->sta->sta : NULL,
560 &key->conf, iter_data); 568 &key->conf, iter_data);
@@ -751,3 +759,135 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
751 } 759 }
752} 760}
753EXPORT_SYMBOL(ieee80211_get_key_rx_seq); 761EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
762
763void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
764 struct ieee80211_key_seq *seq)
765{
766 struct ieee80211_key *key;
767 u64 pn64;
768
769 key = container_of(keyconf, struct ieee80211_key, conf);
770
771 switch (key->conf.cipher) {
772 case WLAN_CIPHER_SUITE_TKIP:
773 key->u.tkip.tx.iv32 = seq->tkip.iv32;
774 key->u.tkip.tx.iv16 = seq->tkip.iv16;
775 break;
776 case WLAN_CIPHER_SUITE_CCMP:
777 pn64 = (u64)seq->ccmp.pn[5] |
778 ((u64)seq->ccmp.pn[4] << 8) |
779 ((u64)seq->ccmp.pn[3] << 16) |
780 ((u64)seq->ccmp.pn[2] << 24) |
781 ((u64)seq->ccmp.pn[1] << 32) |
782 ((u64)seq->ccmp.pn[0] << 40);
783 atomic64_set(&key->u.ccmp.tx_pn, pn64);
784 break;
785 case WLAN_CIPHER_SUITE_AES_CMAC:
786 pn64 = (u64)seq->aes_cmac.pn[5] |
787 ((u64)seq->aes_cmac.pn[4] << 8) |
788 ((u64)seq->aes_cmac.pn[3] << 16) |
789 ((u64)seq->aes_cmac.pn[2] << 24) |
790 ((u64)seq->aes_cmac.pn[1] << 32) |
791 ((u64)seq->aes_cmac.pn[0] << 40);
792 atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
793 break;
794 default:
795 WARN_ON(1);
796 break;
797 }
798}
799EXPORT_SYMBOL_GPL(ieee80211_set_key_tx_seq);
800
801void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
802 int tid, struct ieee80211_key_seq *seq)
803{
804 struct ieee80211_key *key;
805 u8 *pn;
806
807 key = container_of(keyconf, struct ieee80211_key, conf);
808
809 switch (key->conf.cipher) {
810 case WLAN_CIPHER_SUITE_TKIP:
811 if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
812 return;
813 key->u.tkip.rx[tid].iv32 = seq->tkip.iv32;
814 key->u.tkip.rx[tid].iv16 = seq->tkip.iv16;
815 break;
816 case WLAN_CIPHER_SUITE_CCMP:
817 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
818 return;
819 if (tid < 0)
820 pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
821 else
822 pn = key->u.ccmp.rx_pn[tid];
823 memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN);
824 break;
825 case WLAN_CIPHER_SUITE_AES_CMAC:
826 if (WARN_ON(tid != 0))
827 return;
828 pn = key->u.aes_cmac.rx_pn;
829 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
830 break;
831 default:
832 WARN_ON(1);
833 break;
834 }
835}
836EXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq);
837
838void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
839{
840 struct ieee80211_key *key;
841
842 key = container_of(keyconf, struct ieee80211_key, conf);
843
844 assert_key_lock(key->local);
845
846 /*
847 * if key was uploaded, we assume the driver will/has remove(d)
848 * it, so adjust bookkeeping accordingly
849 */
850 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
851 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
852
853 if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
854 (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
855 (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
856 increment_tailroom_need_count(key->sdata);
857 }
858
859 ieee80211_key_free(key, false);
860}
861EXPORT_SYMBOL_GPL(ieee80211_remove_key);
862
863struct ieee80211_key_conf *
864ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
865 struct ieee80211_key_conf *keyconf)
866{
867 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
868 struct ieee80211_local *local = sdata->local;
869 struct ieee80211_key *key;
870 int err;
871
872 if (WARN_ON(!local->wowlan))
873 return ERR_PTR(-EINVAL);
874
875 if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
876 return ERR_PTR(-EINVAL);
877
878 key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
879 keyconf->keylen, keyconf->key,
880 0, NULL);
881 if (IS_ERR(key))
882 return ERR_PTR(PTR_ERR(key));
883
884 if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
885 key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
886
887 err = ieee80211_key_link(key, sdata, NULL);
888 if (err)
889 return ERR_PTR(err);
890
891 return &key->conf;
892}
893EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_add);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d23c5a705a68..e1b34a18b243 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1453,8 +1453,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1453 local->resuming = true; 1453 local->resuming = true;
1454 1454
1455 if (local->wowlan) { 1455 if (local->wowlan) {
1456 local->wowlan = false;
1457 res = drv_resume(local); 1456 res = drv_resume(local);
1457 local->wowlan = false;
1458 if (res < 0) { 1458 if (res < 0) {
1459 local->resuming = false; 1459 local->resuming = false;
1460 return res; 1460 return res;