[PATCH] softmac: return -EAGAIN from getscan while scanning
[safe/jmp/linux-2.6] / net / ieee80211 / ieee80211_crypt_ccmp.c
index 7b62908..78b2d13 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>
@@ -119,7 +118,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 +131,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 +190,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 +224,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 +277,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 +291,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))) {
@@ -429,6 +448,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
        .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,
@@ -436,8 +456,8 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
        .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,
+       .extra_mpdu_prefix_len = CCMP_HDR_LEN,
+       .extra_mpdu_postfix_len = CCMP_MIC_LEN,
        .owner = THIS_MODULE,
 };