linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / ieee80211 / ieee80211_crypt_tkip.c
index 34dba0b..e098832 100644 (file)
@@ -9,6 +9,7 @@
  * more details.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -79,9 +80,10 @@ static void *ieee80211_tkip_init(int key_idx)
 {
        struct ieee80211_tkip_data *priv;
 
-       priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
+       priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
        if (priv == NULL)
                goto fail;
+       memset(priv, 0, sizeof(*priv));
 
        priv->key_idx = key_idx;
 
@@ -269,33 +271,34 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
 #endif
 }
 
-static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
-                             u8 * rc4key, int keylen, void *priv)
+static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_tkip_data *tkey = priv;
        int len;
-       u8 *pos;
+       u8 *rc4key, *pos, *icv;
        struct ieee80211_hdr_4addr *hdr;
+       u32 crc;
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
        if (skb_headroom(skb) < 8 || skb->len < hdr_len)
-               return -1;
-
-       if (rc4key == NULL || keylen < 16)
-               return -1;
+               return NULL;
 
        if (!tkey->tx_phase1_done) {
                tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
                                   tkey->tx_iv32);
                tkey->tx_phase1_done = 1;
        }
+       rc4key = kmalloc(16, GFP_ATOMIC);
+       if (!rc4key)
+               return NULL;
        tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
 
        len = skb->len - hdr_len;
        pos = skb_push(skb, 8);
        memmove(pos, pos + 8, hdr_len);
        pos += hdr_len;
+       icv = skb_put(skb, 4);
 
        *pos++ = *rc4key;
        *pos++ = *(rc4key + 1);
@@ -306,28 +309,28 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
        *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++;
-       }
+       crc = ~crc32_le(~0, pos, len);
+       icv[0] = crc;
+       icv[1] = crc >> 8;
+       icv[2] = crc >> 16;
+       icv[3] = crc >> 24;
 
-       return 8;
+       return rc4key;
 }
 
 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;
+       const u8 *rc4key;
+       u8 *pos;
        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 "
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
                               "TX packet to " MAC_FMT "\n",
                               MAC_ARG(hdr->addr1));
                }
@@ -340,23 +343,22 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        len = skb->len - hdr_len;
        pos = skb->data + hdr_len;
 
-       if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
+       rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
+       if (!rc4key)
                return -1;
 
-       icv = skb_put(skb, 4);
-
-       crc = ~crc32_le(~0, pos, len);
-       icv[0] = crc;
-       icv[1] = crc >> 8;
-       icv[2] = crc >> 16;
-       icv[3] = crc >> 24;
-
        crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
        sg.page = virt_to_page(pos);
        sg.offset = offset_in_page(pos);
        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;
 }
 
@@ -377,7 +379,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
        if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
                if (net_ratelimit()) {
-                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
                               "received packet from " MAC_FMT "\n",
                               MAC_ARG(hdr->addr2));
                }
@@ -500,11 +502,8 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
        struct ieee80211_hdr_4addr *hdr11;
-       u16 stype;
 
        hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
-       stype  = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));
-
        switch (le16_to_cpu(hdr11->frame_ctl) &
                (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
        case IEEE80211_FCTL_TODS:
@@ -525,13 +524,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
                break;
        }
 
-       if (stype & IEEE80211_STYPE_QOS_DATA) {
-               const struct ieee80211_hdr_3addrqos *qoshdr =
-                       (struct ieee80211_hdr_3addrqos *)skb->data;
-               hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
-       } else
-               hdr[12] = 0;            /* priority */
-
+       hdr[12] = 0;            /* priority */
        hdr[13] = hdr[14] = hdr[15] = 0;        /* reserved */
 }
 
@@ -702,7 +695,6 @@ 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,