Merge branch 'upstream-fixes'
[powerpc.git] / net / ieee80211 / ieee80211_crypt_tkip.c
index f973d6c..93def94 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -60,19 +59,30 @@ struct ieee80211_tkip_data {
        /* scratch buffers for virt_to_page() (crypto API) */
        u8 rx_hdr[16], tx_hdr[16];
 
-       struct ieee80211_device *ieee;
+       unsigned long flags;
 };
 
-static void *ieee80211_tkip_init(struct ieee80211_device *ieee, int key_idx)
+static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
+{
+       struct ieee80211_tkip_data *_priv = priv;
+       unsigned long old_flags = _priv->flags;
+       _priv->flags = flags;
+       return old_flags;
+}
+
+static unsigned long ieee80211_tkip_get_flags(void *priv)
+{
+       struct ieee80211_tkip_data *_priv = priv;
+       return _priv->flags;
+}
+
+static void *ieee80211_tkip_init(int key_idx)
 {
        struct ieee80211_tkip_data *priv;
 
-       priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+       priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
        if (priv == NULL)
                goto fail;
-       memset(priv, 0, sizeof(*priv));
-
-       priv->ieee = ieee;
 
        priv->key_idx = key_idx;
 
@@ -260,28 +270,20 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
 #endif
 }
 
-static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
+                             u8 * rc4key, int keylen, void *priv)
 {
        struct ieee80211_tkip_data *tkey = priv;
        int len;
-       u8 rc4key[16], *pos, *icv;
+       u8 *pos;
        struct ieee80211_hdr_4addr *hdr;
-       u32 crc;
-       struct scatterlist sg;
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
-       if (tkey->ieee->tkip_countermeasures) {
-               if (net_ratelimit()) {
-                       printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-                              "TX packet to " MAC_FMT "\n",
-                              tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
-               }
+       if (skb_headroom(skb) < 8 || skb->len < hdr_len)
                return -1;
-       }
 
-       if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
-           skb->len < hdr_len)
+       if (rc4key == NULL || keylen < 16)
                return -1;
 
        if (!tkey->tx_phase1_done) {
@@ -295,17 +297,55 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        pos = skb_push(skb, 8);
        memmove(pos, pos + 8, hdr_len);
        pos += hdr_len;
-       icv = skb_put(skb, 4);
 
-       *pos++ = rc4key[0];
-       *pos++ = rc4key[1];
-       *pos++ = rc4key[2];
+       *pos++ = *rc4key;
+       *pos++ = *(rc4key + 1);
+       *pos++ = *(rc4key + 2);
        *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
        *pos++ = tkey->tx_iv32 & 0xff;
        *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
        *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
        *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
 
+       tkey->tx_iv16++;
+       if (tkey->tx_iv16 == 0) {
+               tkey->tx_phase1_done = 0;
+               tkey->tx_iv32++;
+       }
+
+       return 8;
+}
+
+static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+       struct ieee80211_tkip_data *tkey = priv;
+       int len;
+       u8 rc4key[16], *pos, *icv;
+       u32 crc;
+       struct scatterlist sg;
+
+       if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
+               if (net_ratelimit()) {
+                       struct ieee80211_hdr_4addr *hdr =
+                           (struct ieee80211_hdr_4addr *)skb->data;
+                       printk(KERN_DEBUG ": TKIP countermeasures: dropped "
+                              "TX packet to " MAC_FMT "\n",
+                              MAC_ARG(hdr->addr1));
+               }
+               return -1;
+       }
+
+       if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
+               return -1;
+
+       len = skb->len - hdr_len;
+       pos = skb->data + hdr_len;
+
+       if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
+               return -1;
+
+       icv = skb_put(skb, 4);
+
        crc = ~crc32_le(~0, pos, len);
        icv[0] = crc;
        icv[1] = crc >> 8;
@@ -318,12 +358,6 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        sg.length = len + 4;
        crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
 
-       tkey->tx_iv16++;
-       if (tkey->tx_iv16 == 0) {
-               tkey->tx_phase1_done = 0;
-               tkey->tx_iv32++;
-       }
-
        return 0;
 }
 
@@ -342,11 +376,11 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
-       if (tkey->ieee->tkip_countermeasures) {
+       if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
                if (net_ratelimit()) {
-                       printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+                       printk(KERN_DEBUG ": TKIP countermeasures: dropped "
                               "received packet from " MAC_FMT "\n",
-                              tkey->ieee->dev->name, MAC_ARG(hdr->addr2));
+                              MAC_ARG(hdr->addr2));
                }
                return -1;
        }
@@ -515,7 +549,6 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
        return 0;
 }
 
-#if WIRELESS_EXT >= 18
 static void ieee80211_michael_mic_failure(struct net_device *dev,
                                          struct ieee80211_hdr_4addr *hdr,
                                          int keyidx)
@@ -536,28 +569,6 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
        wrqu.data.length = sizeof(ev);
        wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
 }
-#elif WIRELESS_EXT >= 15
-static void ieee80211_michael_mic_failure(struct net_device *dev,
-                                         struct ieee80211_hdr_4addr *hdr,
-                                         int keyidx)
-{
-       union iwreq_data wrqu;
-       char buf[128];
-
-       /* TODO: needed parameters: count, keyid, key type, TSC */
-       sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
-               MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
-               MAC_ARG(hdr->addr2));
-       memset(&wrqu, 0, sizeof(wrqu));
-       wrqu.data.length = strlen(buf);
-       wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
-}
-#else                          /* WIRELESS_EXT >= 15 */
-static inline void ieee80211_michael_mic_failure(struct net_device *dev, struct ieee80211_hdr_4addr
-                                                *hdr, int keyidx)
-{
-}
-#endif                         /* WIRELESS_EXT >= 15 */
 
 static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
                                        int hdr_len, void *priv)
@@ -683,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
        .name = "TKIP",
        .init = ieee80211_tkip_init,
        .deinit = ieee80211_tkip_deinit,
+       .build_iv = ieee80211_tkip_hdr,
        .encrypt_mpdu = ieee80211_tkip_encrypt,
        .decrypt_mpdu = ieee80211_tkip_decrypt,
        .encrypt_msdu = ieee80211_michael_mic_add,
@@ -693,6 +705,8 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
        .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
        .extra_mpdu_postfix_len = 4,    /* ICV */
        .extra_msdu_postfix_len = 8,    /* MIC */
+       .get_flags = ieee80211_tkip_get_flags,
+       .set_flags = ieee80211_tkip_set_flags,
        .owner = THIS_MODULE,
 };