ieee80211: Add TKIP crypt-build_iv
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 [EMAIL PROTECTED]
--
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index cd82c3e..eb47641 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -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
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c
b/net/ieee80211/ieee80211_crypt_ccmp.c
index 4702217..097bcea 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct cryp
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_
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
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;
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c
b/net/ieee80211/ieee80211_crypt_tkip.c
index e098832..93def94 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -270,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPS
#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_
*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,