Re: [PATCH v4] mac80211: move struct aead_req off the stack

2016-10-17 Thread Johannes Berg
On Mon, 2016-10-17 at 15:05 +0100, Ard Biesheuvel wrote:
> From: Johannes Berg 

That really ought to have been you - I think I may have lost that by
accident. I'll change it.

> In addition, take care not to put any of our own stack allocations
> into
> scatterlists. This involves reserving some extra room when allocating
> the
> aead_request structures, and referring to those allocations in the
> scatter-
> lists (while copying the data from/to the stack before/after the
> crypto
> operation, as appropriate)

I removed the "to the stack after" language, since that doesn't
actually occur :)


> --- a/net/mac80211/aes_cmac.h
> +++ b/net/mac80211/aes_cmac.h
> @@ -11,6 +11,8 @@
>  
>  #include 
>  
> +#define CMAC_AAD_LEN 20

This part (and aes_cmac.c changes) shouldn't have been there, but that
was my mistake - removed.

With that, I've applied this. Will send it to davem tomorrow.

johannes


[PATCH v4] mac80211: move struct aead_req off the stack

2016-10-17 Thread Ard Biesheuvel
From: Johannes Berg 

Some crypto implementations (such as the generic CCM wrapper in crypto/)
use scatterlists to map fields of private data in their struct aead_req.
This means these data structures cannot live in the vmalloc area, which
means that they cannot live on the stack (with CONFIG_VMAP_STACK.)

This currently occurs only with the generic software implementation, but
the private data and usage is implementation specific, so move the whole
data structures off the stack into heap by allocating every time we need
to use them.

In addition, take care not to put any of our own stack allocations into
scatterlists. This involves reserving some extra room when allocating the
aead_request structures, and referring to those allocations in the scatter-
lists (while copying the data from/to the stack before/after the crypto
operation, as appropriate)

Signed-off-by: Johannes Berg 
Signed-off-by: Ard Biesheuvel 
---
 net/mac80211/aes_ccm.c  | 46 +---
 net/mac80211/aes_ccm.h  |  8 ++--
 net/mac80211/aes_cmac.c |  5 +--
 net/mac80211/aes_cmac.h |  2 +
 net/mac80211/aes_gcm.c  | 43 +++---
 net/mac80211/aes_gcm.h  |  6 ++-
 net/mac80211/aes_gmac.c | 26 +--
 net/mac80211/aes_gmac.h |  4 ++
 net/mac80211/wpa.c  | 22 --
 9 files changed, 97 insertions(+), 65 deletions(-)

diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 7663c28ba353..a4e0d59a40dd 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -18,21 +18,24 @@
 #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,
-  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)
 {
struct scatterlist sg[3];
+   struct aead_request *aead_req;
+   int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+   u8 *__aad;
 
-   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;
+   aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
+   if (!aead_req)
+   return -ENOMEM;
 
-   memset(aead_req, 0, sizeof(aead_req_data));
+   __aad = (u8 *)aead_req + reqsize;
+   memcpy(__aad, aad, CCM_AAD_LEN);
 
sg_init_table(sg, 3);
-   sg_set_buf([0], [2], be16_to_cpup((__be16 *)aad));
+   sg_set_buf([0], &__aad[2], be16_to_cpup((__be16 *)__aad));
sg_set_buf([1], data, data_len);
sg_set_buf([2], mic, mic_len);
 
@@ -41,6 +44,9 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 
*b_0, u8 *aad,
aead_request_set_ad(aead_req, sg[0].length);
 
crypto_aead_encrypt(aead_req);
+   kzfree(aead_req);
+
+   return 0;
 }
 
 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
@@ -48,18 +54,23 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 
*b_0, u8 *aad,
  size_t mic_len)
 {
struct scatterlist sg[3];
-   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;
+   struct aead_request *aead_req;
+   int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+   u8 *__aad;
+   int err;
 
if (data_len == 0)
return -EINVAL;
 
-   memset(aead_req, 0, sizeof(aead_req_data));
+   aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
+   if (!aead_req)
+   return -ENOMEM;
+
+   __aad = (u8 *)aead_req + reqsize;
+   memcpy(__aad, aad, CCM_AAD_LEN);
 
sg_init_table(sg, 3);
-   sg_set_buf([0], [2], be16_to_cpup((__be16 *)aad));
+   sg_set_buf([0], &__aad[2], be16_to_cpup((__be16 *)__aad));
sg_set_buf([1], data, data_len);
sg_set_buf([2], mic, mic_len);
 
@@ -67,7 +78,10 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 
*b_0, u8 *aad,
aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
aead_request_set_ad(aead_req, sg[0].length);
 
-   return crypto_aead_decrypt(aead_req);
+   err = crypto_aead_decrypt(aead_req);
+   kzfree(aead_req);
+
+   return err;
 }
 
 struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index 6a73d1e4d186..fcd3254c5cf0 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -12,12 +12,14 @@
 
 #include 
 
+#define CCM_AAD_LEN32
+
 struct