Merge branch '83xx' into for_paulus
[pandora-kernel.git] / net / ieee80211 / ieee80211_crypt_ccmp.c
index 8fc13f4..4926473 100644 (file)
@@ -9,8 +9,6 @@
  * more details.
  */
 
-#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -119,7 +117,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len)
 }
 
 static void ccmp_init_blocks(struct crypto_tfm *tfm,
-                            struct ieee80211_hdr *hdr,
+                            struct ieee80211_hdr_4addr *hdr,
                             u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
 {
        u8 *pos, qc = 0;
@@ -132,7 +130,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
                       (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
        qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
-                      (WLAN_FC_GET_STYPE(fc) & 0x08));
+                      (WLAN_FC_GET_STYPE(fc) & IEEE80211_STYPE_QOS_DATA));
        aad_len = 22;
        if (a4_included)
                aad_len += 6;
@@ -191,26 +189,22 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
 }
 
-static int ieee80211_ccmp_encrypt(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 data_len, i, blocks, last, len;
-       u8 *pos, *mic;
-       struct ieee80211_hdr *hdr;
-       u8 *b0 = key->tx_b0;
-       u8 *b = key->tx_b;
-       u8 *e = key->tx_e;
-       u8 *s0 = key->tx_s0;
+       int i;
+       u8 *pos;
 
-       if (skb_headroom(skb) < CCMP_HDR_LEN ||
-           skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+       if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
                return -1;
 
-       data_len = skb->len - hdr_len;
+       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;
-       mic = skb_put(skb, CCMP_MIC_LEN);
 
        i = CCMP_PN_LEN - 1;
        while (i >= 0) {
@@ -229,7 +223,31 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        *pos++ = key->tx_pn[1];
        *pos++ = key->tx_pn[0];
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       return CCMP_HDR_LEN;
+}
+
+static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+       struct ieee80211_ccmp_data *key = priv;
+       int data_len, i, blocks, last, len;
+       u8 *pos, *mic;
+       struct ieee80211_hdr_4addr *hdr;
+       u8 *b0 = key->tx_b0;
+       u8 *b = key->tx_b;
+       u8 *e = key->tx_e;
+       u8 *s0 = key->tx_s0;
+
+       if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+               return -1;
+
+       data_len = skb->len - hdr_len;
+       len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
+       if (len < 0)
+               return -1;
+
+       pos = skb->data + hdr_len + CCMP_HDR_LEN;
+       mic = skb_put(skb, CCMP_MIC_LEN);
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
        ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
 
        blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
@@ -258,7 +276,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_ccmp_data *key = priv;
        u8 keyidx, *pos;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u8 *b0 = key->rx_b0;
        u8 *b = key->rx_b;
        u8 *a = key->rx_a;
@@ -272,7 +290,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
                return -1;
        }
 
-       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr = (struct ieee80211_hdr_4addr *)skb->data;
        pos = skb->data + hdr_len;
        keyidx = pos[3];
        if (!(keyidx & (1 << 5))) {
@@ -426,19 +444,20 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv)
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
-       .name                   = "CCMP",
-       .init                   = ieee80211_ccmp_init,
-       .deinit                 = ieee80211_ccmp_deinit,
-       .encrypt_mpdu           = ieee80211_ccmp_encrypt,
-       .decrypt_mpdu           = ieee80211_ccmp_decrypt,
-       .encrypt_msdu           = NULL,
-       .decrypt_msdu           = NULL,
-       .set_key                = ieee80211_ccmp_set_key,
-       .get_key                = ieee80211_ccmp_get_key,
-       .print_stats            = ieee80211_ccmp_print_stats,
-       .extra_prefix_len       = CCMP_HDR_LEN,
-       .extra_postfix_len      = CCMP_MIC_LEN,
-       .owner                  = THIS_MODULE,
+       .name = "CCMP",
+       .init = ieee80211_ccmp_init,
+       .deinit = ieee80211_ccmp_deinit,
+       .build_iv = ieee80211_ccmp_hdr,
+       .encrypt_mpdu = ieee80211_ccmp_encrypt,
+       .decrypt_mpdu = ieee80211_ccmp_decrypt,
+       .encrypt_msdu = NULL,
+       .decrypt_msdu = NULL,
+       .set_key = ieee80211_ccmp_set_key,
+       .get_key = ieee80211_ccmp_get_key,
+       .print_stats = ieee80211_ccmp_print_stats,
+       .extra_mpdu_prefix_len = CCMP_HDR_LEN,
+       .extra_mpdu_postfix_len = CCMP_MIC_LEN,
+       .owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_ccmp_init(void)