mac80211: Support BIGTK configuration for Beacon protection
authorJouni Malinen <jouni@codeaurora.org>
Sat, 22 Feb 2020 13:25:44 +0000 (15:25 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 24 Feb 2020 09:35:57 +0000 (10:35 +0100)
Extend mac80211 key configuration to support the new BIGTK with key
index values 6 and 7. Support for actually protecting Beacon frames
(adding the MME in AP mode and checking it in STA mode) is covered in
separate commits.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Link: https://lore.kernel.org/r/20200222132548.20835-3-jouni@codeaurora.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/debugfs_key.c
net/mac80211/debugfs_key.h
net/mac80211/ieee80211_i.h
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/sta_info.h

index a66eff1..a762ba6 100644 (file)
@@ -568,7 +568,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                if (pairwise && key_idx < NUM_DEFAULT_KEYS)
                        key = rcu_dereference(sta->ptk[key_idx]);
                else if (!pairwise &&
-                        key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
+                        key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
+                        NUM_DEFAULT_BEACON_KEYS)
                        key = rcu_dereference(sta->gtk[key_idx]);
        } else
                key = rcu_dereference(sdata->keys[key_idx]);
@@ -680,6 +681,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
        return 0;
 }
 
+static int ieee80211_config_default_beacon_key(struct wiphy *wiphy,
+                                              struct net_device *dev,
+                                              u8 key_idx)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       ieee80211_set_default_beacon_key(sdata, key_idx);
+
+       return 0;
+}
+
 void sta_set_rate_info_tx(struct sta_info *sta,
                          const struct ieee80211_tx_rate *rate,
                          struct rate_info *rinfo)
@@ -3885,6 +3897,7 @@ const struct cfg80211_ops mac80211_config_ops = {
        .get_key = ieee80211_get_key,
        .set_default_key = ieee80211_config_default_key,
        .set_default_mgmt_key = ieee80211_config_default_mgmt_key,
+       .set_default_beacon_key = ieee80211_config_default_beacon_key,
        .start_ap = ieee80211_start_ap,
        .change_beacon = ieee80211_change_beacon,
        .stop_ap = ieee80211_stop_ap,
index 7b8735c..98a7134 100644 (file)
@@ -433,6 +433,37 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda
        sdata->debugfs.default_mgmt_key = NULL;
 }
 
+void
+ieee80211_debugfs_key_add_beacon_default(struct ieee80211_sub_if_data *sdata)
+{
+       char buf[50];
+       struct ieee80211_key *key;
+
+       if (!sdata->vif.debugfs_dir)
+               return;
+
+       key = key_mtx_dereference(sdata->local,
+                                 sdata->default_beacon_key);
+       if (key) {
+               sprintf(buf, "../keys/%d", key->debugfs.cnt);
+               sdata->debugfs.default_beacon_key =
+                       debugfs_create_symlink("default_beacon_key",
+                                              sdata->vif.debugfs_dir, buf);
+       } else {
+               ieee80211_debugfs_key_remove_beacon_default(sdata);
+       }
+}
+
+void
+ieee80211_debugfs_key_remove_beacon_default(struct ieee80211_sub_if_data *sdata)
+{
+       if (!sdata)
+               return;
+
+       debugfs_remove(sdata->debugfs.default_beacon_key);
+       sdata->debugfs.default_beacon_key = NULL;
+}
+
 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
                                   struct sta_info *sta)
 {
index 1cd7b8b..af7cf49 100644 (file)
@@ -10,6 +10,10 @@ void ieee80211_debugfs_key_add_mgmt_default(
        struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_key_remove_mgmt_default(
        struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_add_beacon_default(
+       struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_remove_beacon_default(
+       struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
                                   struct sta_info *sta);
 #else
@@ -26,6 +30,12 @@ static inline void ieee80211_debugfs_key_add_mgmt_default(
 static inline void ieee80211_debugfs_key_remove_mgmt_default(
        struct ieee80211_sub_if_data *sdata)
 {}
+static inline void ieee80211_debugfs_key_add_beacon_default(
+       struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_remove_beacon_default(
+       struct ieee80211_sub_if_data *sdata)
+{}
 static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
                                                 struct sta_info *sta)
 {}
index 8a49d78..de39f9c 100644 (file)
@@ -901,10 +901,13 @@ struct ieee80211_sub_if_data {
        /* bit field of ACM bits (BIT(802.1D tag)) */
        u8 wmm_acm;
 
-       struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
+       struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS +
+                                        NUM_DEFAULT_MGMT_KEYS +
+                                        NUM_DEFAULT_BEACON_KEYS];
        struct ieee80211_key __rcu *default_unicast_key;
        struct ieee80211_key __rcu *default_multicast_key;
        struct ieee80211_key __rcu *default_mgmt_key;
+       struct ieee80211_key __rcu *default_beacon_key;
 
        u16 sequence_number;
        __be16 control_port_protocol;
@@ -978,6 +981,7 @@ struct ieee80211_sub_if_data {
                struct dentry *default_unicast_key;
                struct dentry *default_multicast_key;
                struct dentry *default_mgmt_key;
+               struct dentry *default_beacon_key;
        } debugfs;
 #endif
 
index 54934ef..6354491 100644 (file)
@@ -407,6 +407,31 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&sdata->local->key_mtx);
 }
 
+static void
+__ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
+{
+       struct ieee80211_key *key = NULL;
+
+       assert_key_lock(sdata->local);
+
+       if (idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS &&
+           idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
+           NUM_DEFAULT_BEACON_KEYS)
+               key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
+
+       rcu_assign_pointer(sdata->default_beacon_key, key);
+
+       ieee80211_debugfs_key_update_default(sdata);
+}
+
+void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
+                                     int idx)
+{
+       mutex_lock(&sdata->local->key_mtx);
+       __ieee80211_set_default_beacon_key(sdata, idx);
+       mutex_unlock(&sdata->local->key_mtx);
+}
+
 static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                                  struct sta_info *sta,
                                  bool pairwise,
@@ -415,7 +440,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 {
        int idx;
        int ret = 0;
-       bool defunikey, defmultikey, defmgmtkey;
+       bool defunikey, defmultikey, defmgmtkey, defbeaconkey;
 
        /* caller must provide at least one old/new */
        if (WARN_ON(!new && !old))
@@ -480,6 +505,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                defmgmtkey = old &&
                        old == key_mtx_dereference(sdata->local,
                                                sdata->default_mgmt_key);
+               defbeaconkey = old &&
+                       old == key_mtx_dereference(sdata->local,
+                                                  sdata->default_beacon_key);
 
                if (defunikey && !new)
                        __ieee80211_set_default_key(sdata, -1, true, false);
@@ -487,6 +515,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                        __ieee80211_set_default_key(sdata, -1, false, true);
                if (defmgmtkey && !new)
                        __ieee80211_set_default_mgmt_key(sdata, -1);
+               if (defbeaconkey && !new)
+                       __ieee80211_set_default_beacon_key(sdata, -1);
 
                rcu_assign_pointer(sdata->keys[idx], new);
                if (defunikey && new)
@@ -498,6 +528,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                if (defmgmtkey && new)
                        __ieee80211_set_default_mgmt_key(sdata,
                                                         new->conf.keyidx);
+               if (defbeaconkey && new)
+                       __ieee80211_set_default_beacon_key(sdata,
+                                                          new->conf.keyidx);
        }
 
        if (old)
@@ -515,7 +548,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
        struct ieee80211_key *key;
        int i, j, err;
 
-       if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
+       if (WARN_ON(idx < 0 ||
+                   idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
+                   NUM_DEFAULT_BEACON_KEYS))
                return ERR_PTR(-EINVAL);
 
        key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
@@ -978,6 +1013,7 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
        sdata->crypto_tx_tailroom_pending_dec = 0;
 
        ieee80211_debugfs_key_remove_mgmt_default(sdata);
+       ieee80211_debugfs_key_remove_beacon_default(sdata);
 
        list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
                ieee80211_key_replace(key->sdata, key->sta,
index d6d6e89..7ad72e9 100644 (file)
@@ -17,6 +17,7 @@
 
 #define NUM_DEFAULT_KEYS 4
 #define NUM_DEFAULT_MGMT_KEYS 2
+#define NUM_DEFAULT_BEACON_KEYS 2
 #define INVALID_PTK_KEYIDX 2 /* Keyidx always pointing to a NULL key for PTK */
 
 struct ieee80211_local;
@@ -153,6 +154,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
                               bool uni, bool multi);
 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
                                    int idx);
+void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
+                                     int idx);
 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
                         bool force_synchronize);
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
index c00e285..364a354 100644 (file)
@@ -533,7 +533,9 @@ struct sta_info {
        u8 addr[ETH_ALEN];
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
+       struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS +
+                                       NUM_DEFAULT_MGMT_KEYS +
+                                       NUM_DEFAULT_BEACON_KEYS];
        struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
        u8 ptk_idx;
        struct rate_control_ref *rate_ctrl;