summaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 41b8db37c7c1..42d52cded4c1 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -265,9 +265,24 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
265 sta ? sta->sta.addr : bcast_addr, ret); 265 sta ? sta->sta.addr : bcast_addr, ret);
266} 266}
267 267
268int ieee80211_set_tx_key(struct ieee80211_key *key)
269{
270 struct sta_info *sta = key->sta;
271 struct ieee80211_local *local = key->local;
272 struct ieee80211_key *old;
273
274 assert_key_lock(local);
275
276 old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
277 sta->ptk_idx = key->conf.keyidx;
278 ieee80211_check_fast_xmit(sta);
279
280 return 0;
281}
282
268static int ieee80211_hw_key_replace(struct ieee80211_key *old_key, 283static int ieee80211_hw_key_replace(struct ieee80211_key *old_key,
269 struct ieee80211_key *new_key, 284 struct ieee80211_key *new_key,
270 bool ptk0rekey) 285 bool pairwise)
271{ 286{
272 struct ieee80211_sub_if_data *sdata; 287 struct ieee80211_sub_if_data *sdata;
273 struct ieee80211_local *local; 288 struct ieee80211_local *local;
@@ -284,8 +299,9 @@ static int ieee80211_hw_key_replace(struct ieee80211_key *old_key,
284 assert_key_lock(old_key->local); 299 assert_key_lock(old_key->local);
285 sta = old_key->sta; 300 sta = old_key->sta;
286 301
287 /* PTK only using key ID 0 needs special handling on rekey */ 302 /* Unicast rekey without Extended Key ID needs special handling */
288 if (new_key && sta && ptk0rekey) { 303 if (new_key && sta && pairwise &&
304 rcu_access_pointer(sta->ptk[sta->ptk_idx]) == old_key) {
289 local = old_key->local; 305 local = old_key->local;
290 sdata = old_key->sdata; 306 sdata = old_key->sdata;
291 307
@@ -401,10 +417,6 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
401 417
402 if (old) { 418 if (old) {
403 idx = old->conf.keyidx; 419 idx = old->conf.keyidx;
404 /* TODO: proper implement and test "Extended Key ID for
405 * Individually Addressed Frames" from IEEE 802.11-2016.
406 * Till then always assume only key ID 0 is used for
407 * pairwise keys.*/
408 ret = ieee80211_hw_key_replace(old, new, pairwise); 420 ret = ieee80211_hw_key_replace(old, new, pairwise);
409 } else { 421 } else {
410 /* new must be provided in case old is not */ 422 /* new must be provided in case old is not */
@@ -421,15 +433,20 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
421 if (sta) { 433 if (sta) {
422 if (pairwise) { 434 if (pairwise) {
423 rcu_assign_pointer(sta->ptk[idx], new); 435 rcu_assign_pointer(sta->ptk[idx], new);
424 sta->ptk_idx = idx; 436 if (new &&
425 if (new) { 437 !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) {
438 sta->ptk_idx = idx;
426 clear_sta_flag(sta, WLAN_STA_BLOCK_BA); 439 clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
427 ieee80211_check_fast_xmit(sta); 440 ieee80211_check_fast_xmit(sta);
428 } 441 }
429 } else { 442 } else {
430 rcu_assign_pointer(sta->gtk[idx], new); 443 rcu_assign_pointer(sta->gtk[idx], new);
431 } 444 }
432 if (new) 445 /* Only needed for transition from no key -> key.
446 * Still triggers unnecessary when using Extended Key ID
447 * and installing the second key ID the first time.
448 */
449 if (new && !old)
433 ieee80211_check_fast_rx(sta); 450 ieee80211_check_fast_rx(sta);
434 } else { 451 } else {
435 defunikey = old && 452 defunikey = old &&
@@ -745,16 +762,34 @@ int ieee80211_key_link(struct ieee80211_key *key,
745 * can cause warnings to appear. 762 * can cause warnings to appear.
746 */ 763 */
747 bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; 764 bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
748 int ret; 765 int ret = -EOPNOTSUPP;
749 766
750 mutex_lock(&sdata->local->key_mtx); 767 mutex_lock(&sdata->local->key_mtx);
751 768
752 if (sta && pairwise) 769 if (sta && pairwise) {
770 struct ieee80211_key *alt_key;
771
753 old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]); 772 old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
754 else if (sta) 773 alt_key = key_mtx_dereference(sdata->local, sta->ptk[idx ^ 1]);
774
775 /* The rekey code assumes that the old and new key are using
776 * the same cipher. Enforce the assumption for pairwise keys.
777 */
778 if (key &&
779 ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
780 (old_key && old_key->conf.cipher != key->conf.cipher)))
781 goto out;
782 } else if (sta) {
755 old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); 783 old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
756 else 784 } else {
757 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); 785 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
786 }
787
788 /* Non-pairwise keys must also not switch the cipher on rekey */
789 if (!pairwise) {
790 if (key && old_key && old_key->conf.cipher != key->conf.cipher)
791 goto out;
792 }
758 793
759 /* 794 /*
760 * Silently accept key re-installation without really installing the 795 * Silently accept key re-installation without really installing the