diff options
Diffstat (limited to 'package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch')
-rw-r--r-- | package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch | 757 |
1 files changed, 507 insertions, 250 deletions
diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch index 0febc57b3f..aa44149aed 100644 --- a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch +++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch @@ -1,270 +1,388 @@ ---- a/net/mac80211/Kconfig -+++ b/net/mac80211/Kconfig -@@ -5,8 +5,6 @@ config MAC80211 - depends on CRYPTO - depends on CRYPTO_ARC4 - depends on CRYPTO_AES -- select BPAUTO_CRYPTO_CCM -- depends on CRYPTO_GCM - depends on CRYPTO_CMAC - depends on CRC32 - ---help--- --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile -@@ -16,9 +16,7 @@ mac80211-y := \ +@@ -6,7 +6,6 @@ mac80211-y := \ + driver-ops.o \ + sta_info.o \ + wep.o \ +- aead_api.o \ + wpa.o \ + scan.o offchannel.o \ + ht.o agg-tx.o agg-rx.o \ +@@ -16,8 +15,8 @@ mac80211-y := \ + rate.o \ michael.o \ tkip.o \ - aes_ccm.o \ -- aes_gcm.o \ ++ aes_ccm.o \ aes_cmac.o \ - aes_gmac.o \ fils_aead.o \ cfg.o \ ethtool.o \ ---- a/net/mac80211/aes_ccm.c -+++ b/net/mac80211/aes_ccm.c -@@ -13,103 +13,132 @@ - #include <linux/types.h> - #include <linux/err.h> - #include <crypto/aead.h> -+#include <crypto/aes.h> - - #include <net/mac80211.h> - #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, -- size_t mic_len) -+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0, -+ u8 *a, u8 *b) - { +--- a/net/mac80211/aead_api.c ++++ /dev/null +@@ -1,115 +0,0 @@ +-/* +- * Copyright 2003-2004, Instant802 Networks, Inc. +- * Copyright 2005-2006, Devicescape Software, Inc. +- * Copyright 2014-2015, Qualcomm Atheros, Inc. +- * +- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> +- * +- * 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. +- */ +- +-#include <linux/kernel.h> +-#include <linux/types.h> +-#include <linux/err.h> +-#include <linux/scatterlist.h> +-#include <crypto/aead.h> +- +-#include "aead_api.h" +- +-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, +- u8 *data, size_t data_len, u8 *mic) +-{ +- size_t mic_len = crypto_aead_authsize(tfm); - struct scatterlist sg[3]; - struct aead_request *aead_req; - int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); - u8 *__aad; -+ int i; - -- aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); +- +- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); - if (!aead_req) - return -ENOMEM; -+ crypto_cipher_encrypt_one(tfm, b, b_0); - +- - __aad = (u8 *)aead_req + reqsize; -- memcpy(__aad, aad, CCM_AAD_LEN); -+ /* Extra Authenticate-only data (always two AES blocks) */ -+ for (i = 0; i < AES_BLOCK_SIZE; i++) -+ aad[i] ^= b[i]; -+ crypto_cipher_encrypt_one(tfm, b, aad); - +- memcpy(__aad, aad, aad_len); +- - sg_init_table(sg, 3); -- sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); +- sg_set_buf(&sg[0], __aad, aad_len); - sg_set_buf(&sg[1], data, data_len); - sg_set_buf(&sg[2], mic, mic_len); -+ aad += AES_BLOCK_SIZE; - +- - aead_request_set_tfm(aead_req, tfm); - aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); - aead_request_set_ad(aead_req, sg[0].length); -+ for (i = 0; i < AES_BLOCK_SIZE; i++) -+ aad[i] ^= b[i]; -+ crypto_cipher_encrypt_one(tfm, a, aad); - +- - crypto_aead_encrypt(aead_req); - kzfree(aead_req); -+ /* Mask out bits from auth-only-b_0 */ -+ b_0[0] &= 0x07; - +- - return 0; -+ /* S_0 is used to encrypt T (= MIC) */ -+ 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, -- size_t mic_len) -+ -+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, -+ u8 *data, size_t data_len, u8 *mic, -+ size_t mic_len) - { +-} +- +-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, +- u8 *data, size_t data_len, u8 *mic) +-{ +- size_t mic_len = crypto_aead_authsize(tfm); - struct scatterlist sg[3]; - struct aead_request *aead_req; - int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); - u8 *__aad; - int err; -+ int i, j, last_len, num_blocks; -+ u8 b[AES_BLOCK_SIZE]; -+ u8 s_0[AES_BLOCK_SIZE]; -+ u8 e[AES_BLOCK_SIZE]; -+ u8 *pos, *cpos; - +- - if (data_len == 0) - return -EINVAL; -+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); -+ last_len = data_len % AES_BLOCK_SIZE; -+ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); - -- aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); +- +- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); - if (!aead_req) - return -ENOMEM; -+ /* Process payload blocks */ -+ pos = data; -+ cpos = data; -+ for (j = 1; j <= num_blocks; j++) { -+ int blen = (j == num_blocks && last_len) ? -+ last_len : AES_BLOCK_SIZE; - +- - __aad = (u8 *)aead_req + reqsize; -- memcpy(__aad, aad, CCM_AAD_LEN); -+ /* Authentication followed by encryption */ -+ for (i = 0; i < blen; i++) -+ b[i] ^= pos[i]; -+ crypto_cipher_encrypt_one(tfm, b, b); - +- memcpy(__aad, aad, aad_len); +- - sg_init_table(sg, 3); -- sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); +- sg_set_buf(&sg[0], __aad, aad_len); - sg_set_buf(&sg[1], data, data_len); - sg_set_buf(&sg[2], mic, mic_len); -+ b_0[14] = (j >> 8) & 0xff; -+ b_0[15] = j & 0xff; -+ crypto_cipher_encrypt_one(tfm, e, b_0); -+ for (i = 0; i < blen; i++) -+ *cpos++ = *pos++ ^ e[i]; -+ } - +- - aead_request_set_tfm(aead_req, tfm); - aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); - aead_request_set_ad(aead_req, sg[0].length); -+ for (i = 0; i < mic_len; i++) -+ mic[i] = b[i] ^ s_0[i]; -+} - +- - err = crypto_aead_decrypt(aead_req); - kzfree(aead_req); -+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, -+ u8 *data, size_t data_len, u8 *mic, -+ size_t mic_len) -+{ -+ int i, j, last_len, num_blocks; -+ u8 *pos, *cpos; -+ u8 a[AES_BLOCK_SIZE]; -+ u8 b[AES_BLOCK_SIZE]; -+ u8 s_0[AES_BLOCK_SIZE]; - +- - return err; -+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); -+ last_len = data_len % AES_BLOCK_SIZE; -+ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b); -+ -+ /* Process payload blocks */ -+ cpos = data; -+ pos = data; -+ for (j = 1; j <= num_blocks; j++) { -+ int blen = (j == num_blocks && last_len) ? -+ last_len : AES_BLOCK_SIZE; -+ -+ /* Decryption followed by authentication */ -+ b_0[14] = (j >> 8) & 0xff; -+ b_0[15] = j & 0xff; -+ crypto_cipher_encrypt_one(tfm, b, b_0); -+ for (i = 0; i < blen; i++) { -+ *pos = *cpos++ ^ b[i]; -+ a[i] ^= *pos++; -+ } -+ crypto_cipher_encrypt_one(tfm, a, a); -+ } -+ -+ for (i = 0; i < mic_len; i++) { -+ if ((mic[i] ^ s_0[i]) != a[i]) -+ return -1; -+ } -+ -+ return 0; - } - --struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], -- size_t key_len, -- size_t mic_len) -+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], -+ size_t key_len, -+ size_t mic_len) - { +-} +- +-struct crypto_aead * +-aead_key_setup_encrypt(const char *alg, 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); +- tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return tfm; -+ struct crypto_cipher *tfm; - +- - err = crypto_aead_setkey(tfm, key, key_len); - if (err) - goto free_aead; - err = crypto_aead_setauthsize(tfm, mic_len); - if (err) - goto free_aead; -+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); -+ if (!IS_ERR(tfm)) -+ crypto_cipher_setkey(tfm, key, key_len); - - return tfm; +- +- return tfm; - -free_aead: - crypto_free_aead(tfm); - return ERR_PTR(err); - } - --void ieee80211_aes_key_free(struct crypto_aead *tfm) -+ -+void ieee80211_aes_key_free(struct crypto_cipher *tfm) - { +-} +- +-void aead_key_free(struct crypto_aead *tfm) +-{ - crypto_free_aead(tfm); -+ crypto_free_cipher(tfm); - } ---- a/net/mac80211/aes_gmac.h -+++ b/net/mac80211/aes_gmac.h -@@ -15,10 +15,22 @@ - #define GMAC_MIC_LEN 16 - #define GMAC_NONCE_LEN 12 +-} +--- a/net/mac80211/aead_api.h ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* +- * 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. +- */ +- +-#ifndef _AEAD_API_H +-#define _AEAD_API_H +- +-#include <crypto/aead.h> +-#include <linux/crypto.h> +- +-struct crypto_aead * +-aead_key_setup_encrypt(const char *alg, const u8 key[], +- size_t key_len, size_t mic_len); +- +-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +- size_t aad_len, u8 *data, +- size_t data_len, u8 *mic); +- +-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +- size_t aad_len, u8 *data, +- size_t data_len, u8 *mic); +- +-void aead_key_free(struct crypto_aead *tfm); +- +-#endif /* _AEAD_API_H */ +--- a/net/mac80211/aes_ccm.h ++++ b/net/mac80211/aes_ccm.h +@@ -10,39 +10,17 @@ + #ifndef AES_CCM_H + #define AES_CCM_H --struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], -- size_t key_len); --int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, -- const u8 *data, size_t data_len, u8 *mic); --void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); -+static inline struct crypto_aead * -+ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len) +-#include "aead_api.h" +- +-#define CCM_AAD_LEN 32 +- +-static inline struct crypto_aead * +-ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len) +-{ +- return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len); +-} +- +-static inline int +-ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, +- u8 *b_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) +-{ +- return aead_encrypt(tfm, b_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); +-} +- +-static inline int +-ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, +- u8 *b_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) +-{ +- return aead_decrypt(tfm, b_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); +-} ++#include <linux/crypto.h> + +-static inline void ieee80211_aes_key_free(struct crypto_aead *tfm) +-{ +- return aead_key_free(tfm); +-} ++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], ++ size_t key_len, ++ size_t mic_len); ++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len); ++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len); ++void ieee80211_aes_key_free(struct crypto_cipher *tfm); + + #endif /* AES_CCM_H */ +--- /dev/null ++++ b/net/mac80211/aes_gcm.c +@@ -0,0 +1,109 @@ ++/* ++ * Copyright 2014-2015, Qualcomm Atheros, Inc. ++ * ++ * 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. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/types.h> ++#include <linux/err.h> ++#include <crypto/aead.h> ++ ++#include <net/mac80211.h> ++#include "key.h" ++#include "aes_gcm.h" ++ ++int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) +{ -+ return NULL; ++ struct scatterlist sg[3]; ++ struct aead_request *aead_req; ++ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); ++ u8 *__aad; ++ ++ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); ++ if (!aead_req) ++ return -ENOMEM; ++ ++ __aad = (u8 *)aead_req + reqsize; ++ memcpy(__aad, aad, GCM_AAD_LEN); ++ ++ sg_init_table(sg, 3); ++ sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); ++ sg_set_buf(&sg[1], data, data_len); ++ sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); ++ ++ aead_request_set_tfm(aead_req, tfm); ++ aead_request_set_crypt(aead_req, sg, sg, data_len, j_0); ++ aead_request_set_ad(aead_req, sg[0].length); ++ ++ crypto_aead_encrypt(aead_req); ++ kzfree(aead_req); ++ return 0; +} + -+static inline int -+ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, -+ const u8 *data, size_t data_len, u8 *mic) ++int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) +{ -+ return -EOPNOTSUPP; ++ struct scatterlist sg[3]; ++ struct aead_request *aead_req; ++ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); ++ u8 *__aad; ++ int err; ++ ++ if (data_len == 0) ++ return -EINVAL; ++ ++ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); ++ if (!aead_req) ++ return -ENOMEM; ++ ++ __aad = (u8 *)aead_req + reqsize; ++ memcpy(__aad, aad, GCM_AAD_LEN); ++ ++ sg_init_table(sg, 3); ++ sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); ++ sg_set_buf(&sg[1], data, data_len); ++ sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); ++ ++ aead_request_set_tfm(aead_req, tfm); ++ aead_request_set_crypt(aead_req, sg, sg, ++ data_len + IEEE80211_GCMP_MIC_LEN, j_0); ++ aead_request_set_ad(aead_req, sg[0].length); ++ ++ err = crypto_aead_decrypt(aead_req); ++ kzfree(aead_req); ++ ++ return err; +} + -+static inline void -+ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) ++struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], ++ size_t key_len) ++{ ++ struct crypto_aead *tfm; ++ int err; ++ ++ tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) ++ return tfm; ++ ++ err = crypto_aead_setkey(tfm, key, key_len); ++ if (err) ++ goto free_aead; ++ err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN); ++ if (err) ++ goto free_aead; ++ ++ return tfm; ++ ++free_aead: ++ crypto_free_aead(tfm); ++ return ERR_PTR(err); ++} ++ ++void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) +{ ++ crypto_free_aead(tfm); +} +--- a/net/mac80211/aes_gcm.h ++++ b/net/mac80211/aes_gcm.h +@@ -9,38 +9,30 @@ + #ifndef AES_GCM_H + #define AES_GCM_H - #endif /* AES_GMAC_H */ ---- a/net/mac80211/key.h -+++ b/net/mac80211/key.h -@@ -88,7 +88,7 @@ struct ieee80211_key { - * Management frames. - */ - u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; -- struct crypto_aead *tfm; -+ struct crypto_cipher *tfm; - u32 replays; /* dot11RSNAStatsCCMPReplays */ - } ccmp; - struct { +-#include "aead_api.h" +- +-#define GCM_AAD_LEN 32 ++#include <linux/crypto.h> + +-static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, +- u8 *j_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) ++static inline void ++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) + { +- return aead_encrypt(tfm, j_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); + } + +-static inline int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, +- u8 *j_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) ++static inline int ++ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) + { +- return aead_decrypt(tfm, j_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); ++ return -EOPNOTSUPP; + } + + static inline struct crypto_aead * + ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) + { +- return aead_key_setup_encrypt("gcm(aes)", key, +- key_len, IEEE80211_GCMP_MIC_LEN); ++ return NULL; + } + +-static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) ++static inline void ++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) + { +- return aead_key_free(tfm); + } + + #endif /* AES_GCM_H */ --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -306,7 +306,8 @@ ieee80211_crypto_tkip_decrypt(struct iee @@ -318,7 +436,7 @@ 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, -- skb_put(skb, mic_len), mic_len); +- skb_put(skb, mic_len)); + ccmp_special_blocks(skb, pn, b_0, aad, len); + ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, + skb_put(skb, mic_len), mic_len); @@ -327,7 +445,7 @@ } -@@ -537,7 +536,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee +@@ -537,13 +536,13 @@ ieee80211_crypto_ccmp_decrypt(struct iee u8 aad[2 * AES_BLOCK_SIZE]; u8 b_0[AES_BLOCK_SIZE]; /* hardware didn't decrypt/verify MIC */ @@ -336,6 +454,13 @@ if (ieee80211_aes_ccm_decrypt( key->u.ccmp.tfm, b_0, aad, + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, + data_len, +- skb->data + skb->len - mic_len)) ++ skb->data + skb->len - mic_len, mic_len)) + return RX_DROP_UNUSABLE; + } + @@ -639,7 +638,7 @@ static int gcmp_encrypt_skb(struct ieee8 u8 *pos; u8 pn[6]; @@ -379,70 +504,202 @@ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; if (!ieee80211_is_mgmt(hdr->frame_control)) ---- a/net/mac80211/aes_ccm.h -+++ b/net/mac80211/aes_ccm.h -@@ -12,17 +12,15 @@ - - #include <linux/crypto.h> - --#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, -- size_t mic_len); --int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, -+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], -+ size_t key_len, -+ size_t mic_len); +--- /dev/null ++++ b/net/mac80211/aes_ccm.c +@@ -0,0 +1,144 @@ ++/* ++ * Copyright 2003-2004, Instant802 Networks, Inc. ++ * Copyright 2005-2006, Devicescape Software, Inc. ++ * ++ * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/types.h> ++#include <linux/err.h> ++#include <crypto/aead.h> ++#include <crypto/aes.h> ++ ++#include <net/mac80211.h> ++#include "key.h" ++#include "aes_ccm.h" ++ ++static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0, ++ u8 *a, u8 *b) ++{ ++ int i; ++ ++ crypto_cipher_encrypt_one(tfm, b, b_0); ++ ++ /* Extra Authenticate-only data (always two AES blocks) */ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ aad[i] ^= b[i]; ++ crypto_cipher_encrypt_one(tfm, b, aad); ++ ++ aad += AES_BLOCK_SIZE; ++ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ aad[i] ^= b[i]; ++ crypto_cipher_encrypt_one(tfm, a, aad); ++ ++ /* Mask out bits from auth-only-b_0 */ ++ b_0[0] &= 0x07; ++ ++ /* S_0 is used to encrypt T (= MIC) */ ++ b_0[14] = 0; ++ b_0[15] = 0; ++ crypto_cipher_encrypt_one(tfm, s_0, b_0); ++} ++ ++ +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, + u8 *data, size_t data_len, u8 *mic, -+ size_t mic_len); ++ size_t mic_len) ++{ ++ int i, j, last_len, num_blocks; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ u8 e[AES_BLOCK_SIZE]; ++ u8 *pos, *cpos; ++ ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); ++ ++ /* Process payload blocks */ ++ pos = data; ++ cpos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; ++ ++ /* Authentication followed by encryption */ ++ for (i = 0; i < blen; i++) ++ b[i] ^= pos[i]; ++ crypto_cipher_encrypt_one(tfm, b, b); ++ ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, e, b_0); ++ for (i = 0; i < blen; i++) ++ *cpos++ = *pos++ ^ e[i]; ++ } ++ ++ for (i = 0; i < mic_len; i++) ++ mic[i] = b[i] ^ s_0[i]; ++} ++ +int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, 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 crypto_cipher *tfm); - - #endif /* AES_CCM_H */ ---- a/net/mac80211/aes_gcm.h -+++ b/net/mac80211/aes_gcm.h -@@ -11,14 +11,28 @@ - - #include <linux/crypto.h> - --#define GCM_AAD_LEN 32 -+static inline void -+ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, -+ u8 *data, size_t data_len, u8 *mic) ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len) +{ ++ int i, j, last_len, num_blocks; ++ u8 *pos, *cpos; ++ u8 a[AES_BLOCK_SIZE]; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b); ++ ++ /* Process payload blocks */ ++ cpos = data; ++ pos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; ++ ++ /* Decryption followed by authentication */ ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, b, b_0); ++ for (i = 0; i < blen; i++) { ++ *pos = *cpos++ ^ b[i]; ++ a[i] ^= *pos++; ++ } ++ crypto_cipher_encrypt_one(tfm, a, a); ++ } ++ ++ for (i = 0; i < mic_len; i++) { ++ if ((mic[i] ^ s_0[i]) != a[i]) ++ return -1; ++ } ++ ++ return 0; +} - --int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, -- u8 *data, size_t data_len, u8 *mic); --int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, -- u8 *data, size_t data_len, u8 *mic); --struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], -- size_t key_len); --void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); -+static inline int -+ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, -+ u8 *data, size_t data_len, u8 *mic) ++ ++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], ++ size_t key_len, ++ size_t mic_len) +{ -+ return -EOPNOTSUPP; ++ struct crypto_cipher *tfm; ++ ++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); ++ if (!IS_ERR(tfm)) ++ crypto_cipher_setkey(tfm, key, key_len); ++ ++ return tfm; +} + ++ ++void ieee80211_aes_key_free(struct crypto_cipher *tfm) ++{ ++ crypto_free_cipher(tfm); ++} +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -5,8 +5,6 @@ config MAC80211 + depends on CRYPTO + depends on CRYPTO_ARC4 + depends on CRYPTO_AES +- depends on CRYPTO_CCM +- depends on CRYPTO_GCM + depends on CRYPTO_CMAC + depends on CRC32 + ---help--- +--- a/net/mac80211/aes_gmac.h ++++ b/net/mac80211/aes_gmac.h +@@ -15,10 +15,22 @@ + #define GMAC_MIC_LEN 16 + #define GMAC_NONCE_LEN 12 + +-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], +- size_t key_len); +-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, +- const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); +static inline struct crypto_aead * -+ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) ++ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len) +{ -+ return NULL; ++ return NULL; ++} ++ ++static inline int ++ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, ++ const u8 *data, size_t data_len, u8 *mic) ++{ ++ return -EOPNOTSUPP; +} + +static inline void -+ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) ++ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) +{ +} - #endif /* AES_GCM_H */ + #endif /* AES_GMAC_H */ +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -88,7 +88,7 @@ struct ieee80211_key { + * Management frames. + */ + u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; +- struct crypto_aead *tfm; ++ struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCCMPReplays */ + } ccmp; + struct { |