mac80211: support GTK rekey offload
authorJohannes Berg <johannes.berg@intel.com>
Tue, 5 Jul 2011 14:35:41 +0000 (16:35 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 6 Jul 2011 19:05:43 +0000 (15:05 -0400)
This adds the necessary mac80211 APIs to support
GTK rekey offload, mirroring the functionality
from cfg80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/driver-ops.h
net/mac80211/driver-trace.h
net/mac80211/key.c

index 4703c0f07ba403c466d3866abfc5ec582c39bfaf..2474019f47d3723a7b39455928f85c6533b3cae4 100644 (file)
@@ -1700,6 +1700,12 @@ enum ieee80211_ampdu_mlme_action {
  *     which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
  *     The callback must be atomic.
  *
+ * @set_rekey_data: If the device supports GTK rekeying, for example while the
+ *     host is suspended, it can assign this callback to retrieve the data
+ *     necessary to do GTK rekeying, this is the KEK, KCK and replay counter.
+ *     After rekeying was done it should (for example during resume) notify
+ *     userspace of the new replay counter using ieee80211_gtk_rekey_notify().
+ *
  * @hw_scan: Ask the hardware to service the scan request, no need to start
  *     the scan state machine in stack. The scan must honour the channel
  *     configuration done by the regulatory agent in the wiphy's
@@ -1912,6 +1918,9 @@ struct ieee80211_ops {
                                struct ieee80211_key_conf *conf,
                                struct ieee80211_sta *sta,
                                u32 iv32, u16 *phase1key);
+       void (*set_rekey_data)(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              struct cfg80211_gtk_rekey_data *data);
        int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                       struct cfg80211_scan_request *req);
        void (*cancel_hw_scan)(struct ieee80211_hw *hw,
@@ -2585,6 +2594,17 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
                                struct sk_buff *skb,
                                enum ieee80211_tkip_key_type type, u8 *key);
+
+/**
+ * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
+ * @vif: virtual interface the rekeying was done on
+ * @bssid: The BSSID of the AP, for checking association
+ * @replay_ctr: the new replay counter after GTK rekeying
+ * @gfp: allocation flags
+ */
+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
+                               const u8 *replay_ctr, gfp_t gfp);
+
 /**
  * ieee80211_wake_queue - wake specific queue
  * @hw: pointer as obtained from ieee80211_alloc_hw().
index 9fe22cc393c8b1e7e222b63bff22fb1fb9934c3b..295ab747663f45955ccfe0a79d2541a741984d72 100644 (file)
@@ -2101,6 +2101,21 @@ static void ieee80211_get_ringparam(struct wiphy *wiphy,
        drv_get_ringparam(local, tx, tx_max, rx, rx_max);
 }
 
+static int ieee80211_set_rekey_data(struct wiphy *wiphy,
+                                   struct net_device *dev,
+                                   struct cfg80211_gtk_rekey_data *data)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (!local->ops->set_rekey_data)
+               return -EOPNOTSUPP;
+
+       drv_set_rekey_data(local, sdata, data);
+
+       return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -2163,4 +2178,5 @@ struct cfg80211_ops mac80211_config_ops = {
        .get_antenna = ieee80211_get_antenna,
        .set_ringparam = ieee80211_set_ringparam,
        .get_ringparam = ieee80211_get_ringparam,
+       .set_rekey_data = ieee80211_set_rekey_data,
 };
index 0e7e4268ddf657e0739373f8541772c1b32d2ffe..edd2dd79c9be36020870bcee014d09f9ee241e25 100644 (file)
@@ -647,4 +647,14 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
        return ret;
 }
 
+static inline void drv_set_rekey_data(struct ieee80211_local *local,
+                                     struct ieee80211_sub_if_data *sdata,
+                                     struct cfg80211_gtk_rekey_data *data)
+{
+       trace_drv_set_rekey_data(local, sdata, data);
+       if (local->ops->set_rekey_data)
+               local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
+       trace_drv_return_void(local);
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
index 3cb6795e926db0cb0e834ce4df5087d598a4a571..31a9dfa81f6529292a6a8cde4337d91ed26d6fa9 100644 (file)
@@ -1024,6 +1024,34 @@ TRACE_EVENT(drv_set_bitrate_mask,
        )
 );
 
+TRACE_EVENT(drv_set_rekey_data,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct cfg80211_gtk_rekey_data *data),
+
+       TP_ARGS(local, sdata, data),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               __array(u8, kek, NL80211_KEK_LEN)
+               __array(u8, kck, NL80211_KCK_LEN)
+               __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               memcpy(__entry->kek, data->kek, NL80211_KEK_LEN);
+               memcpy(__entry->kck, data->kck, NL80211_KCK_LEN);
+               memcpy(__entry->replay_ctr, data->replay_ctr,
+                      NL80211_REPLAY_CTR_LEN);
+       ),
+
+       TP_printk(LOCAL_PR_FMT VIF_PR_FMT,
+                 LOCAL_PR_ARG, VIF_PR_ARG)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
@@ -1293,6 +1321,27 @@ DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired,
        TP_ARGS(local)
 );
 
+TRACE_EVENT(api_gtk_rekey_notify,
+       TP_PROTO(struct ieee80211_sub_if_data *sdata,
+                const u8 *bssid, const u8 *replay_ctr),
+
+       TP_ARGS(sdata, bssid, replay_ctr),
+
+       TP_STRUCT__entry(
+               VIF_ENTRY
+               __array(u8, bssid, ETH_ALEN)
+               __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
+       ),
+
+       TP_fast_assign(
+               VIF_ASSIGN;
+               memcpy(__entry->bssid, bssid, ETH_ALEN);
+               memcpy(__entry->replay_ctr, replay_ctr, NL80211_REPLAY_CTR_LEN);
+       ),
+
+       TP_printk(VIF_PR_FMT, VIF_PR_ARG)
+);
+
 /*
  * Tracing for internal functions
  * (which may also be called in response to driver calls)
index fcab5fe726a113b22cede63a59a389858cab3cdc..1208a7878bfd1cc25a252bdbb77eaf4ebab02163 100644 (file)
@@ -613,3 +613,15 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
 
        mutex_unlock(&sdata->local->key_mtx);
 }
+
+
+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
+                               const u8 *replay_ctr, gfp_t gfp)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+       trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);
+
+       cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
+}
+EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);