wifi: iwlwifi: mvm: Refactor security key update after D3
authorYedidya Benshimol <yedidya.ben.shimol@intel.com>
Wed, 21 Jun 2023 11:49:50 +0000 (14:49 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 21 Jun 2023 12:14:34 +0000 (14:14 +0200)
In the D3 resume flow, use two different iterating functions
to go over the old keys and update the new ones

Signed-off-by: Yedidya Benshimol <yedidya.ben.shimol@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230621144844.a2442844c224.I598ed742c7aaa5414702f03f694f2dc0874bc077@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/d3.c

index 6d1007f24b4aa91ba33e4e60d1019eb309a35984..d3eb13f3372b014a51ffc34f1e2778aa8a3587f7 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -1779,18 +1779,17 @@ struct iwl_mvm_d3_gtk_iter_data {
        struct iwl_wowlan_status_data *status;
        void *last_gtk;
        u32 cipher;
-       bool find_phase, unhandled_cipher;
+       bool unhandled_cipher;
        int num_keys;
 };
 
-static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
-                                  struct ieee80211_vif *vif,
-                                  struct ieee80211_sta *sta,
-                                  struct ieee80211_key_conf *key,
-                                  void *_data)
+static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
+                                     struct ieee80211_vif *vif,
+                                     struct ieee80211_sta *sta,
+                                     struct ieee80211_key_conf *key,
+                                     void *_data)
 {
        struct iwl_mvm_d3_gtk_iter_data *data = _data;
-       struct iwl_wowlan_status_data *status = data->status;
 
        if (data->unhandled_cipher)
                return;
@@ -1805,51 +1804,56 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
        case WLAN_CIPHER_SUITE_GCMP_256:
        case WLAN_CIPHER_SUITE_TKIP:
                /* we support these */
+               data->last_gtk = key;
+               data->cipher = key->cipher;
                break;
        default:
-               /* everything else (even CMAC for MFP) - disconnect from AP */
+               /* everything else - disconnect from AP */
                data->unhandled_cipher = true;
                return;
        }
 
        data->num_keys++;
+}
 
-       /*
-        * pairwise key - update sequence counters only;
-        * note that this assumes no TDLS sessions are active
-        */
-       if (sta) {
-               if (data->find_phase)
-                       return;
+static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_sta *sta,
+                                  struct ieee80211_key_conf *key,
+                                  void *_data)
+{
+       struct iwl_mvm_d3_gtk_iter_data *data = _data;
+       struct iwl_wowlan_status_data *status = data->status;
 
-               switch (key->cipher) {
-               case WLAN_CIPHER_SUITE_CCMP:
-               case WLAN_CIPHER_SUITE_GCMP:
-               case WLAN_CIPHER_SUITE_GCMP_256:
+       if (data->unhandled_cipher)
+               return;
+
+       switch (key->cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               /* ignore WEP completely, nothing to do */
+               return;
+       case WLAN_CIPHER_SUITE_CCMP:
+       case WLAN_CIPHER_SUITE_GCMP:
+       case WLAN_CIPHER_SUITE_GCMP_256:
+               if (sta) {
                        atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn);
                        iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);
-                       break;
-               case WLAN_CIPHER_SUITE_TKIP:
+                       return;
+               }
+               fallthrough;
+       case WLAN_CIPHER_SUITE_TKIP:
+               if (sta) {
                        atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn);
                        iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);
-                       break;
+                       return;
                }
+               if (data->status->num_of_gtk_rekeys)
+                       ieee80211_remove_key(key);
 
-               /* that's it for this key */
-               return;
+               if (data->last_gtk == key)
+                       iwl_mvm_set_key_rx_seq(key, data->status, false);
        }
-
-       if (data->find_phase) {
-               data->last_gtk = key;
-               data->cipher = key->cipher;
-               return;
-       }
-
-       if (data->status->num_of_gtk_rekeys)
-               ieee80211_remove_key(key);
-
-       if (data->last_gtk == key)
-               iwl_mvm_set_key_rx_seq(key, data->status, false);
 }
 
 static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
@@ -1872,9 +1876,8 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                return false;
 
        /* find last GTK that we used initially, if any */
-       gtkdata.find_phase = true;
        ieee80211_iter_keys(mvm->hw, vif,
-                           iwl_mvm_d3_update_keys, &gtkdata);
+                           iwl_mvm_d3_find_last_keys, &gtkdata);
        /* not trying to keep connections with MFP/unhandled ciphers */
        if (gtkdata.unhandled_cipher)
                return false;
@@ -1887,7 +1890,6 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
         * invalidate all other GTKs that might still exist and update
         * the one that we used
         */
-       gtkdata.find_phase = false;
        ieee80211_iter_keys(mvm->hw, vif,
                            iwl_mvm_d3_update_keys, &gtkdata);