|
@@ -52,8 +52,10 @@ struct ieee80211_tkip_data {
|
|
|
|
|
|
int key_idx;
|
|
|
|
|
|
- struct crypto_tfm *tfm_arc4;
|
|
|
- struct crypto_tfm *tfm_michael;
|
|
|
+ struct crypto_tfm *tx_tfm_arc4;
|
|
|
+ struct crypto_tfm *tx_tfm_michael;
|
|
|
+ struct crypto_tfm *rx_tfm_arc4;
|
|
|
+ struct crypto_tfm *rx_tfm_michael;
|
|
|
|
|
|
/* scratch buffers for virt_to_page() (crypto API) */
|
|
|
u8 rx_hdr[16], tx_hdr[16];
|
|
@@ -85,15 +87,29 @@ static void *ieee80211_tkip_init(int key_idx)
|
|
|
|
|
|
priv->key_idx = key_idx;
|
|
|
|
|
|
- priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
|
|
|
- if (priv->tfm_arc4 == NULL) {
|
|
|
+ priv->tx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
|
|
|
+ if (priv->tx_tfm_arc4 == NULL) {
|
|
|
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
|
|
"crypto API arc4\n");
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
|
|
|
- if (priv->tfm_michael == NULL) {
|
|
|
+ priv->tx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
|
|
|
+ if (priv->tx_tfm_michael == NULL) {
|
|
|
+ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
|
|
+ "crypto API michael_mic\n");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ priv->rx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
|
|
|
+ if (priv->rx_tfm_arc4 == NULL) {
|
|
|
+ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
|
|
+ "crypto API arc4\n");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ priv->rx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
|
|
|
+ if (priv->rx_tfm_michael == NULL) {
|
|
|
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
|
|
"crypto API michael_mic\n");
|
|
|
goto fail;
|
|
@@ -103,10 +119,14 @@ static void *ieee80211_tkip_init(int key_idx)
|
|
|
|
|
|
fail:
|
|
|
if (priv) {
|
|
|
- if (priv->tfm_michael)
|
|
|
- crypto_free_tfm(priv->tfm_michael);
|
|
|
- if (priv->tfm_arc4)
|
|
|
- crypto_free_tfm(priv->tfm_arc4);
|
|
|
+ if (priv->tx_tfm_michael)
|
|
|
+ crypto_free_tfm(priv->tx_tfm_michael);
|
|
|
+ if (priv->tx_tfm_arc4)
|
|
|
+ crypto_free_tfm(priv->tx_tfm_arc4);
|
|
|
+ if (priv->rx_tfm_michael)
|
|
|
+ crypto_free_tfm(priv->rx_tfm_michael);
|
|
|
+ if (priv->rx_tfm_arc4)
|
|
|
+ crypto_free_tfm(priv->rx_tfm_arc4);
|
|
|
kfree(priv);
|
|
|
}
|
|
|
|
|
@@ -116,10 +136,16 @@ static void *ieee80211_tkip_init(int key_idx)
|
|
|
static void ieee80211_tkip_deinit(void *priv)
|
|
|
{
|
|
|
struct ieee80211_tkip_data *_priv = priv;
|
|
|
- if (_priv && _priv->tfm_michael)
|
|
|
- crypto_free_tfm(_priv->tfm_michael);
|
|
|
- if (_priv && _priv->tfm_arc4)
|
|
|
- crypto_free_tfm(_priv->tfm_arc4);
|
|
|
+ if (_priv) {
|
|
|
+ if (_priv->tx_tfm_michael)
|
|
|
+ crypto_free_tfm(_priv->tx_tfm_michael);
|
|
|
+ if (_priv->tx_tfm_arc4)
|
|
|
+ crypto_free_tfm(_priv->tx_tfm_arc4);
|
|
|
+ if (_priv->rx_tfm_michael)
|
|
|
+ crypto_free_tfm(_priv->rx_tfm_michael);
|
|
|
+ if (_priv->rx_tfm_arc4)
|
|
|
+ crypto_free_tfm(_priv->rx_tfm_arc4);
|
|
|
+ }
|
|
|
kfree(priv);
|
|
|
}
|
|
|
|
|
@@ -351,11 +377,11 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|
|
icv[2] = crc >> 16;
|
|
|
icv[3] = crc >> 24;
|
|
|
|
|
|
- crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
|
|
|
+ crypto_cipher_setkey(tkey->tx_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);
|
|
|
+ crypto_cipher_encrypt(tkey->tx_tfm_arc4, &sg, &sg, len + 4);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -446,11 +472,11 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|
|
|
|
|
plen = skb->len - hdr_len - 12;
|
|
|
|
|
|
- crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
|
|
|
+ crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
|
|
|
sg.page = virt_to_page(pos);
|
|
|
sg.offset = offset_in_page(pos);
|
|
|
sg.length = plen + 4;
|
|
|
- crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
|
|
|
+ crypto_cipher_decrypt(tkey->rx_tfm_arc4, &sg, &sg, plen + 4);
|
|
|
|
|
|
crc = ~crc32_le(~0, pos, plen);
|
|
|
icv[0] = crc;
|
|
@@ -484,12 +510,12 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|
|
return keyidx;
|
|
|
}
|
|
|
|
|
|
-static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
|
|
|
+static int michael_mic(struct crypto_tfm *tfm_michael, u8 * key, u8 * hdr,
|
|
|
u8 * data, size_t data_len, u8 * mic)
|
|
|
{
|
|
|
struct scatterlist sg[2];
|
|
|
|
|
|
- if (tkey->tfm_michael == NULL) {
|
|
|
+ if (tfm_michael == NULL) {
|
|
|
printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
|
|
|
return -1;
|
|
|
}
|
|
@@ -501,10 +527,10 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
|
|
|
sg[1].offset = offset_in_page(data);
|
|
|
sg[1].length = data_len;
|
|
|
|
|
|
- crypto_digest_init(tkey->tfm_michael);
|
|
|
- crypto_digest_setkey(tkey->tfm_michael, key, 8);
|
|
|
- crypto_digest_update(tkey->tfm_michael, sg, 2);
|
|
|
- crypto_digest_final(tkey->tfm_michael, mic);
|
|
|
+ crypto_digest_init(tfm_michael);
|
|
|
+ crypto_digest_setkey(tfm_michael, key, 8);
|
|
|
+ crypto_digest_update(tfm_michael, sg, 2);
|
|
|
+ crypto_digest_final(tfm_michael, mic);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -562,7 +588,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
|
|
|
|
|
|
michael_mic_hdr(skb, tkey->tx_hdr);
|
|
|
pos = skb_put(skb, 8);
|
|
|
- if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
|
|
|
+ if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
|
|
|
skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
|
|
|
return -1;
|
|
|
|
|
@@ -600,7 +626,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
|
|
return -1;
|
|
|
|
|
|
michael_mic_hdr(skb, tkey->rx_hdr);
|
|
|
- if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
|
|
|
+ if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
|
|
|
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
|
|
|
return -1;
|
|
|
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
|
|
@@ -630,14 +656,18 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
|
|
|
{
|
|
|
struct ieee80211_tkip_data *tkey = priv;
|
|
|
int keyidx;
|
|
|
- struct crypto_tfm *tfm = tkey->tfm_michael;
|
|
|
- struct crypto_tfm *tfm2 = tkey->tfm_arc4;
|
|
|
+ struct crypto_tfm *tfm = tkey->tx_tfm_michael;
|
|
|
+ struct crypto_tfm *tfm2 = tkey->tx_tfm_arc4;
|
|
|
+ struct crypto_tfm *tfm3 = tkey->rx_tfm_michael;
|
|
|
+ struct crypto_tfm *tfm4 = tkey->rx_tfm_arc4;
|
|
|
|
|
|
keyidx = tkey->key_idx;
|
|
|
memset(tkey, 0, sizeof(*tkey));
|
|
|
tkey->key_idx = keyidx;
|
|
|
- tkey->tfm_michael = tfm;
|
|
|
- tkey->tfm_arc4 = tfm2;
|
|
|
+ tkey->tx_tfm_michael = tfm;
|
|
|
+ tkey->tx_tfm_arc4 = tfm2;
|
|
|
+ tkey->rx_tfm_michael = tfm3;
|
|
|
+ tkey->rx_tfm_arc4 = tfm4;
|
|
|
if (len == TKIP_KEY_LEN) {
|
|
|
memcpy(tkey->key, key, TKIP_KEY_LEN);
|
|
|
tkey->key_set = 1;
|