depends on CRYPTO
depends on CRYPTO_ARC4
depends on CRYPTO_AES
-- depends on CRYPTO_CCM
+- select BACKPORT_CRYPTO_CCM
depends on CRC32
select BACKPORT_AVERAGE
---help---
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
-@@ -19,75 +17,134 @@
+@@ -19,76 +17,134 @@
#include "key.h"
#include "aes_ccm.h"
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
- u8 *data, size_t data_len, u8 *mic)
+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
- {
-- struct scatterlist assoc, pt, ct[2];
-- struct {
-- struct aead_request req;
-- u8 priv[crypto_aead_reqsize(tfm)];
-- } aead_req;
--
-- memset(&aead_req, 0, sizeof(aead_req));
--
-- sg_init_one(&pt, data, data_len);
-- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
-- sg_init_table(ct, 2);
-- sg_set_buf(&ct[0], data, data_len);
-- sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
--
-- aead_request_set_tfm(&aead_req.req, tfm);
-- aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
-- aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0);
++{
+ int i;
+ u8 *b_0, *aad, *b, *s_0;
-
-- crypto_aead_encrypt(&aead_req.req);
++
+ b_0 = scratch + 3 * AES_BLOCK_SIZE;
+ aad = scratch + 4 * AES_BLOCK_SIZE;
+ b = scratch;
+ b_0[14] = 0;
+ b_0[15] = 0;
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
- }
-
--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-- u8 *data, size_t data_len, u8 *mic)
++}
++
+
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+ u8 *data, size_t data_len,
+ u8 *cdata, u8 *mic)
{
- struct scatterlist assoc, pt, ct[2];
-- struct {
-- struct aead_request req;
-- u8 priv[crypto_aead_reqsize(tfm)];
-- } aead_req;
++ int i, j, last_len, num_blocks;
++ u8 *pos, *cpos, *b, *s_0, *e, *b_0;
+
+- char aead_req_data[sizeof(struct aead_request) +
+- crypto_aead_reqsize(tfm)]
+- __aligned(__alignof__(struct aead_request));
+- struct aead_request *aead_req = (void *) aead_req_data;
-
-- memset(&aead_req, 0, sizeof(aead_req));
+- memset(aead_req, 0, sizeof(aead_req_data));
-
- sg_init_one(&pt, data, data_len);
- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
- sg_set_buf(&ct[0], data, data_len);
- sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
-
-- aead_request_set_tfm(&aead_req.req, tfm);
-- aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
-- aead_request_set_crypt(&aead_req.req, ct, &pt,
-- data_len + IEEE80211_CCMP_MIC_LEN, b_0);
-+ int i, j, last_len, num_blocks;
-+ u8 *pos, *cpos, *b, *s_0, *e, *b_0;
-+
+- aead_request_set_tfm(aead_req, tfm);
+- aead_request_set_assoc(aead_req, &assoc, assoc.length);
+- aead_request_set_crypt(aead_req, &pt, ct, data_len, b_0);
+ b = scratch;
+ s_0 = scratch + AES_BLOCK_SIZE;
+ e = scratch + 2 * AES_BLOCK_SIZE;
+ *cpos++ = *pos++ ^ e[i];
+ }
-- return crypto_aead_decrypt(&aead_req.req);
+- crypto_aead_encrypt(aead_req);
+ for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
+ mic[i] = b[i] ^ s_0[i];
}
--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
+-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+- u8 *data, size_t data_len, u8 *mic)
+
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+ u8 *cdata, size_t data_len, u8 *mic, u8 *data)
{
-- struct crypto_aead *tfm;
-- int err;
+- struct scatterlist assoc, pt, ct[2];
+- char aead_req_data[sizeof(struct aead_request) +
+- crypto_aead_reqsize(tfm)]
+- __aligned(__alignof__(struct aead_request));
+- struct aead_request *aead_req = (void *) aead_req_data;
+-
+- memset(aead_req, 0, sizeof(aead_req_data));
+-
+- sg_init_one(&pt, data, data_len);
+- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+- sg_init_table(ct, 2);
+- sg_set_buf(&ct[0], data, data_len);
+- sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
+-
+- aead_request_set_tfm(aead_req, tfm);
+- aead_request_set_assoc(aead_req, &assoc, assoc.length);
+- aead_request_set_crypt(aead_req, ct, &pt,
+- data_len + IEEE80211_CCMP_MIC_LEN, b_0);
+ int i, j, last_len, num_blocks;
+ u8 *pos, *cpos, *b, *s_0, *a, *b_0;
-
-- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
-- if (IS_ERR(tfm))
-- return tfm;
--
-- err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
-- if (!err)
-- err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
-- if (!err)
-- return tfm;
++
+ b = scratch;
+ s_0 = scratch + AES_BLOCK_SIZE;
+ a = scratch + 2 * AES_BLOCK_SIZE;
+ return -1;
+ }
-- crypto_free_aead(tfm);
-- return ERR_PTR(err);
+- return crypto_aead_decrypt(aead_req);
+ return 0;
}
--void ieee80211_aes_key_free(struct crypto_aead *tfm)
+-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
+
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
-+{
+ {
+- struct crypto_aead *tfm;
+- int err;
+ struct crypto_cipher *tfm;
-+
+
+- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
+- if (IS_ERR(tfm))
+- return tfm;
+-
+- err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
+- if (!err)
+- err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
+- if (!err)
+- return tfm;
+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+ if (!IS_ERR(tfm))
+ crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
-+
+
+- crypto_free_aead(tfm);
+- return ERR_PTR(err);
+ return tfm;
-+}
-+
+ }
+
+-void ieee80211_aes_key_free(struct crypto_aead *tfm)
+
+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
{
#endif /* AES_CCM_H */
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
-@@ -83,7 +83,7 @@ struct ieee80211_key {
+@@ -84,7 +84,7 @@ struct ieee80211_key {
* Management frames.
*/
u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
struct {
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
-@@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
+@@ -304,15 +304,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
}
--static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
- int encrypted)
++ int encrypted)
{
__le16 mask_fc;
int a4_included, mgmt;
/*
* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
* Retry, PwrMgt, MoreData; set Protected
-@@ -332,21 +338,20 @@ static void ccmp_special_blocks(struct s
+@@ -334,21 +341,20 @@ static void ccmp_special_blocks(struct s
else
qos_tid = 0;
/* AAD (extra authenticate-only data) / masked 802.11 header
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
-@@ -402,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
+@@ -404,8 +410,7 @@ static int ccmp_encrypt_skb(struct ieee8
u8 *pos;
u8 pn[6];
u64 pn64;
if (info->control.hw_key &&
!(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
-@@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
+@@ -461,9 +466,9 @@ static int ccmp_encrypt_skb(struct ieee8
return 0;
pos += IEEE80211_CCMP_HDR_LEN;
-- ccmp_special_blocks(skb, pn, b_0, aad, 0);
+- ccmp_special_blocks(skb, pn, b_0, aad);
- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
- skb_put(skb, IEEE80211_CCMP_MIC_LEN));
+ ccmp_special_blocks(skb, pn, scratch, 0);
return 0;
}
-@@ -521,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+@@ -526,16 +531,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
}
if (!(status->flag & RX_FLAG_DECRYPTED)) {
- u8 b_0[AES_BLOCK_SIZE];
+ u8 scratch[6 * AES_BLOCK_SIZE];
/* hardware didn't decrypt/verify MIC */
-- ccmp_special_blocks(skb, pn, b_0, aad, 1);
+- ccmp_special_blocks(skb, pn, b_0, aad);
+ ccmp_special_blocks(skb, pn, scratch, 1);
if (ieee80211_aes_ccm_decrypt(