mac80211: allows driver to request a Phase 1 RX key
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 20 Mar 2008 13:06:42 +0000 (15:06 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 25 Mar 2008 20:41:53 +0000 (16:41 -0400)
This patch makes mac80211 able to send a phase1 key for TKIP
decryption.
This is needed for drivers that don't do the rekeying by themselves
(i.e. iwlwifi). Upon IV16 wrap around, the packet is decrypted in SW,
if decryption is ok, mac80211 calls to update_tkip_key  with a new
phase 1 RX key.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/tkip.c
net/mac80211/tkip.h
net/mac80211/wpa.c

index 2a134582fc16020e60597606a7c5035ab33f2f81..48428a6b9109290e0067270a6ad835547fb73917 100644 (file)
@@ -827,6 +827,16 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
  * parameter is guaranteed to be valid until another call to set_key()
  * removes it, but it can only be used as a cookie to differentiate
  * keys.
+ *
+ * In TKIP some HW need to be provided a phase 1 key, for RX decryption
+ * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key
+ * handler.
+ * The update_tkip_key() call updates the driver with the new phase 1 key.
+ * This happens everytime the iv16 wraps around (every 65536 packets). The
+ * set_key() call will happen only once for each key (unless the AP did
+ * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
+ * provided by udpate_tkip_key only. The trigger that makes mac80211 call this
+ * handler is software decryption with wrap around of iv16.
  */
 
 /**
@@ -1003,6 +1013,10 @@ enum ieee80211_ampdu_mlme_action {
  *     and remove_interface calls, i.e. while the interface with the
  *     given local_address is enabled.
  *
+ * @update_tkip_key: See the section "Hardware crypto acceleration"
+ *     This callback will be called in the context of Rx. Called for drivers
+ *     which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
+ *
  * @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 registered
@@ -1094,6 +1108,9 @@ struct ieee80211_ops {
        int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                       const u8 *local_address, const u8 *address,
                       struct ieee80211_key_conf *key);
+       void (*update_tkip_key)(struct ieee80211_hw *hw,
+                       struct ieee80211_key_conf *conf, const u8 *address,
+                       u32 iv32, u16 *phase1key);
        int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
        int (*get_stats)(struct ieee80211_hw *hw,
                         struct ieee80211_low_level_stats *stats);
index 5c36b2df3fafb90d8d7eac7b112202884ab6c2f3..45d59f19c29f2b4585d7e79ade403f09441b6ee4 100644 (file)
@@ -291,7 +291,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
 int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
                                struct ieee80211_key *key,
                                u8 *payload, size_t payload_len, u8 *ta,
-                               int only_iv, int queue,
+                               u8 *ra, int only_iv, int queue,
                                u32 *out_iv32, u16 *out_iv16)
 {
        u32 iv32;
@@ -368,6 +368,19 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
                        printk("\n");
                }
 #endif /* CONFIG_TKIP_DEBUG */
+               if (key->local->ops->update_tkip_key &&
+                       key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+                       u8 bcast[ETH_ALEN] =
+                               {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+                       u8 *sta_addr = key->sta->addr;
+
+                       if (is_multicast_ether_addr(ra))
+                               sta_addr = bcast;
+
+                       key->local->ops->update_tkip_key(
+                               local_to_hw(key->local), &key->conf,
+                               sta_addr, iv32, key->u.tkip.p1k_rx[queue]);
+               }
        }
 
        tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
index 73d8ef2a93b0f9ed5821d3a0686b44e65f6e0c63..ffaee3253e1923e7c017df1a4f938a1392f669f1 100644 (file)
@@ -31,7 +31,7 @@ enum {
 int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
                                struct ieee80211_key *key,
                                u8 *payload, size_t payload_len, u8 *ta,
-                               int only_iv, int queue,
+                               u8 *ra, int only_iv, int queue,
                                u32 *out_iv32, u16 *out_iv16);
 
 #endif /* TKIP_H */
index df0b7341efc8d03c5957b2620d9a76b2fcda1508..45709ada8fee2c2ba222d7e8fb5743e62b2f6d27 100644 (file)
@@ -312,7 +312,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
        res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
                                          key, skb->data + hdrlen,
                                          skb->len - hdrlen, rx->sta->addr,
-                                         hwaccel, rx->queue,
+                                         hdr->addr1, hwaccel, rx->queue,
                                          &rx->tkip_iv32,
                                          &rx->tkip_iv16);
        if (res != TKIP_DECRYPT_OK || wpa_test) {