@@ -10,6 +10,7 @@
*/
#include <linux/kernel.h>
+#include <linux/percpu.h>
#include <linux/types.h>
#include <linux/err.h>
#include <crypto/aead.h>
@@ -18,13 +19,13 @@
#include "key.h"
#include "aes_ccm.h"
-int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
- u8 *data, size_t data_len, u8 *mic,
+int ieee80211_aes_ccm_encrypt(struct ieee80211_ccmp_aead *ccmp, u8 *b_0,
+ u8 *aad, u8 *data, size_t data_len, u8 *mic,
size_t mic_len)
{
struct scatterlist sg[3];
struct aead_request *aead_req;
- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(ccmp->tfm);
u8 *__aad;
aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
@@ -39,7 +40,7 @@ int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
sg_set_buf(&sg[1], data, data_len);
sg_set_buf(&sg[2], mic, mic_len);
- aead_request_set_tfm(aead_req, tfm);
+ aead_request_set_tfm(aead_req, ccmp->tfm);
aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
aead_request_set_ad(aead_req, sg[0].length);
@@ -49,13 +50,13 @@ int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
return 0;
}
-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 ieee80211_ccmp_aead *ccmp, u8 *b_0,
+ u8 *aad, u8 *data, size_t data_len, u8 *mic,
size_t mic_len)
{
struct scatterlist sg[3];
struct aead_request *aead_req;
- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(ccmp->tfm);
u8 *__aad;
int err;
@@ -74,7 +75,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
sg_set_buf(&sg[1], data, data_len);
sg_set_buf(&sg[2], mic, mic_len);
- aead_request_set_tfm(aead_req, tfm);
+ aead_request_set_tfm(aead_req, ccmp->tfm);
aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
aead_request_set_ad(aead_req, sg[0].length);
@@ -84,16 +85,17 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
return err;
}
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
- size_t key_len,
- size_t mic_len)
+int ieee80211_aes_key_setup_encrypt(struct ieee80211_ccmp_aead *ccmp,
+ const u8 key[],
+ size_t key_len,
+ size_t mic_len)
{
struct crypto_aead *tfm;
int err;
tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm))
- return tfm;
+ return PTR_ERR(tfm);
err = crypto_aead_setkey(tfm, key, key_len);
if (err)
@@ -102,14 +104,15 @@ struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
if (err)
goto free_aead;
- return tfm;
+ ccmp->tfm = tfm;
+ return 0;
free_aead:
crypto_free_aead(tfm);
- return ERR_PTR(err);
+ return err;
}
-void ieee80211_aes_key_free(struct crypto_aead *tfm)
+void ieee80211_aes_key_free(struct ieee80211_ccmp_aead *ccmp)
{
- crypto_free_aead(tfm);
+ crypto_free_aead(ccmp->tfm);
}
@@ -14,15 +14,15 @@
#define CCM_AAD_LEN 32
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
- size_t key_len,
- size_t mic_len);
-int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
- u8 *data, size_t data_len, u8 *mic,
+int ieee80211_aes_key_setup_encrypt(struct ieee80211_ccmp_aead *ccmp,
+ const u8 key[], size_t key_len,
+ size_t mic_len);
+int ieee80211_aes_ccm_encrypt(struct ieee80211_ccmp_aead *ccmp, u8 *b_0,
+ u8 *aad, u8 *data, size_t data_len, u8 *mic,
size_t mic_len);
-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 ieee80211_ccmp_aead *ccmp, u8 *b_0,
+ u8 *aad, u8 *data, size_t data_len, u8 *mic,
size_t mic_len);
-void ieee80211_aes_key_free(struct crypto_aead *tfm);
+void ieee80211_aes_key_free(struct ieee80211_ccmp_aead *ccmp);
#endif /* AES_CCM_H */
@@ -431,10 +431,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
* Initialize AES key state here as an optimization so that
* it does not need to be initialized for every packet.
*/
- key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
- key_data, key_len, IEEE80211_CCMP_MIC_LEN);
- if (IS_ERR(key->u.ccmp.tfm)) {
- err = PTR_ERR(key->u.ccmp.tfm);
+ err = ieee80211_aes_key_setup_encrypt(&key->u.ccmp, key_data,
+ key_len, IEEE80211_CCMP_MIC_LEN);
+ if (err) {
kfree(key);
return ERR_PTR(err);
}
@@ -449,10 +448,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
/* Initialize AES key state here as an optimization so that
* it does not need to be initialized for every packet.
*/
- key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
- key_data, key_len, IEEE80211_CCMP_256_MIC_LEN);
- if (IS_ERR(key->u.ccmp.tfm)) {
- err = PTR_ERR(key->u.ccmp.tfm);
+ err = ieee80211_aes_key_setup_encrypt(&key->u.ccmp, key_data,
+ key_len, IEEE80211_CCMP_256_MIC_LEN);
+ if (err) {
kfree(key);
return ERR_PTR(err);
}
@@ -545,7 +543,7 @@ static void ieee80211_key_free_common(struct ieee80211_key *key)
switch (key->conf.cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
- ieee80211_aes_key_free(key->u.ccmp.tfm);
+ ieee80211_aes_key_free(&key->u.ccmp);
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
@@ -80,7 +80,7 @@ struct ieee80211_key {
/* number of mic failures */
u32 mic_failures;
} tkip;
- struct {
+ struct ieee80211_ccmp_aead {
/*
* Last received packet number. The first
* IEEE80211_NUM_TIDS counters are used with Data
@@ -461,7 +461,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
pos += IEEE80211_CCMP_HDR_LEN;
ccmp_special_blocks(skb, pn, b_0, aad);
- return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+ return ieee80211_aes_ccm_encrypt(&key->u.ccmp, b_0, aad, pos, len,
skb_put(skb, mic_len), mic_len);
}
@@ -538,7 +538,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
ccmp_special_blocks(skb, pn, b_0, aad);
if (ieee80211_aes_ccm_decrypt(
- key->u.ccmp.tfm, b_0, aad,
+ &key->u.ccmp, b_0, aad,
skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
data_len,
skb->data + skb->len - mic_len, mic_len))
As a prepatory change to allow per CPU caching of request structures, refactor the key allocation routine so we can access per key data beyond the core AEAD transform easily. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- net/mac80211/aes_ccm.c | 35 +++++++++++--------- net/mac80211/aes_ccm.h | 16 ++++----- net/mac80211/key.c | 16 ++++----- net/mac80211/key.h | 2 +- net/mac80211/wpa.c | 4 +-- 5 files changed, 37 insertions(+), 36 deletions(-) -- 2.7.4