]> err.no Git - linux-2.6/commitdiff
[PATCH] ieee80211: Add TKIP crypt->build_iv
authorZhu Yi <yi.zhu@intel.com>
Thu, 19 Jan 2006 08:22:32 +0000 (16:22 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 27 Jan 2006 22:08:07 +0000 (17:08 -0500)
This patch adds ieee80211 TKIP build_iv() method to support hardwares
that can do TKIP encryption but relies on ieee80211 layer to build
the IV. It also changes the build_iv() interface to return the key
if possible after the IV is built (this is required by TKIP).

Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/ieee80211_crypt.h
net/ieee80211/ieee80211_crypt_ccmp.c
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_crypt_wep.c
net/ieee80211/ieee80211_tx.c

index cd82c3e998e42860698716feadf6bad275e3ac76..eb476414fd726701d032e9e517751b9d3f7e38df 100644 (file)
@@ -47,7 +47,8 @@ struct ieee80211_crypto_ops {
        /* deinitialize crypto context and free allocated private data */
        void (*deinit) (void *priv);
 
-       int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
+       int (*build_iv) (struct sk_buff * skb, int hdr_len,
+                        u8 *key, int keylen, void *priv);
 
        /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
         * value from decrypt_mpdu is passed as the keyidx value for
index 4702217285032c57dda4ea1b6f1494bd12e64af2..097bcea2129f5ab5a78a81b852b002fd304c8321 100644 (file)
@@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
 }
 
-static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
+                             u8 *aeskey, int keylen, void *priv)
 {
        struct ieee80211_ccmp_data *key = priv;
        int i;
@@ -199,6 +200,9 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
        if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
                return -1;
 
+       if (aeskey != NULL && keylen >= CCMP_TK_LEN)
+               memcpy(aeskey, key->key, CCMP_TK_LEN);
+
        pos = skb_push(skb, CCMP_HDR_LEN);
        memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
        pos += hdr_len;
@@ -238,7 +242,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
                return -1;
 
        data_len = skb->len - hdr_len;
-       len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
+       len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
        if (len < 0)
                return -1;
 
index de56a47edb0058ff4b70d0c50b5a7ad43fe1f820..93def94c1b3253e6fca9c960f39be0c5b2404998 100644 (file)
@@ -270,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
 #endif
 }
 
-static u8 *ieee80211_tkip_hdr(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, *pos, *icv;
+       u8 *pos;
        struct ieee80211_hdr_4addr *hdr;
-       u32 crc;
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
        if (skb_headroom(skb) < 8 || skb->len < hdr_len)
-               return NULL;
+               return -1;
+
+       if (rc4key == NULL || keylen < 16)
+               return -1;
 
        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);
@@ -308,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
        *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
        *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
 
-       crc = ~crc32_le(~0, pos, len);
-       icv[0] = crc;
-       icv[1] = crc >> 8;
-       icv[2] = crc >> 16;
-       icv[3] = crc >> 24;
+       tkey->tx_iv16++;
+       if (tkey->tx_iv16 == 0) {
+               tkey->tx_phase1_done = 0;
+               tkey->tx_iv32++;
+       }
 
-       return rc4key;
+       return 8;
 }
 
 static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_tkip_data *tkey = priv;
        int len;
-       const u8 *rc4key;
-       u8 *pos;
+       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 "
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
                               "TX packet to " MAC_FMT "\n",
                               MAC_ARG(hdr->addr1));
                }
@@ -342,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        len = skb->len - hdr_len;
        pos = skb->data + hdr_len;
 
-       rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
-       if (!rc4key)
+       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;
+       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;
 }
 
@@ -378,7 +378,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));
                }
@@ -694,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,
index f8dca31be5dd6b23e1090740fff257280078f6ed..649e581fa565c323859e804cf4ea13f1e9c6359c 100644 (file)
@@ -76,7 +76,8 @@ static void prism2_wep_deinit(void *priv)
 }
 
 /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
-static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv)
+static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
+                              u8 *key, int keylen, void *priv)
 {
        struct prism2_wep_data *wep = priv;
        u32 klen, len;
@@ -131,7 +132,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
                return -1;
        
        /* add the IV to the frame */
-       if (prism2_wep_build_iv(skb, hdr_len, priv))
+       if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
                return -1;
        
        /* Copy the IV into the first 3 bytes of the key */
index 0949803b9c7dd60f8d4b5a4b4aad38c54e47e7c7..8b4332f533945c4109d31debed4aebcbf310a9f9 100644 (file)
@@ -470,7 +470,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                        atomic_inc(&crypt->refcnt);
                        if (crypt->ops->build_iv)
                                crypt->ops->build_iv(skb_frag, hdr_len,
-                                                    crypt->priv);
+                                     ieee->sec.keys[ieee->sec.active_key],
+                                     ieee->sec.key_sizes[ieee->sec.active_key],
+                                     crypt->priv);
                        atomic_dec(&crypt->refcnt);
                }