On 17 October 2016 at 09:03, Johannes Berg <johan...@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.b...@intel.com>
>
> 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.
>
> This pattern already exists in the IPsec ESP driver, but in the future,
> we may want/need to improve upon this, e.g. by using a slab cache.
>
> (Based on Ard's patch, but that was missing error handling and GCM/GMAC)
>
> Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
> Signed-off-by: Johannes Berg <johannes.b...@intel.com>
> ---
> v3: remove superfluous aead_request_set_tfm() calls

Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org>

> ---
>  net/mac80211/aes_ccm.c  | 36 +++++++++++++++++++-----------------
>  net/mac80211/aes_ccm.h  |  6 +++---
>  net/mac80211/aes_gcm.c  | 33 +++++++++++++++++----------------
>  net/mac80211/aes_gcm.h  |  4 ++--
>  net/mac80211/aes_gmac.c | 11 +++++------
>  net/mac80211/wpa.c      | 12 ++++--------
>  6 files changed, 50 insertions(+), 52 deletions(-)
>
> diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
> index 7663c28ba353..8e898a6e8de8 100644
> --- a/net/mac80211/aes_ccm.c
> +++ b/net/mac80211/aes_ccm.c
> @@ -18,29 +18,29 @@
>  #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;
>
> -       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));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         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, mic_len);
>
> -       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);
>
>         crypto_aead_encrypt(aead_req);
> +       aead_request_free(aead_req);
> +
> +       return 0;
>  }
>
>  int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
> @@ -48,26 +48,28 @@ 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 err;
>
>         if (data_len == 0)
>                 return -EINVAL;
>
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         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, mic_len);
>
> -       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);
>
> -       return crypto_aead_decrypt(aead_req);
> +       err = crypto_aead_decrypt(aead_req);
> +       aead_request_free(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..03e21b0995e3 100644
> --- a/net/mac80211/aes_ccm.h
> +++ b/net/mac80211/aes_ccm.h
> @@ -15,9 +15,9 @@
>  struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
>                                                     size_t key_len,
>                                                     size_t mic_len);
> -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);
>  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);
> diff --git a/net/mac80211/aes_gcm.c b/net/mac80211/aes_gcm.c
> index 3afe361fd27c..831054c6c756 100644
> --- a/net/mac80211/aes_gcm.c
> +++ b/net/mac80211/aes_gcm.c
> @@ -15,55 +15,56 @@
>  #include "key.h"
>  #include "aes_gcm.h"
>
> -void 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_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
> +                             u8 *data, size_t data_len, u8 *mic)
>  {
>         struct scatterlist sg[3];
> +       struct aead_request *aead_req;
>
> -       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));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         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);
> +       aead_request_free(aead_req);
> +       return 0;
>  }
>
>  int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
>                               u8 *data, size_t data_len, u8 *mic)
>  {
>         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 err;
>
>         if (data_len == 0)
>                 return -EINVAL;
>
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         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);
>
> -       return crypto_aead_decrypt(aead_req);
> +       err = crypto_aead_decrypt(aead_req);
> +       aead_request_free(aead_req);
> +
> +       return err;
>  }
>
>  struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
> diff --git a/net/mac80211/aes_gcm.h b/net/mac80211/aes_gcm.h
> index 1347fda6b76a..b36503cd7716 100644
> --- a/net/mac80211/aes_gcm.h
> +++ b/net/mac80211/aes_gcm.h
> @@ -11,8 +11,8 @@
>
>  #include <linux/crypto.h>
>
> -void 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_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[],
> diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
> index 3ddd927aaf30..6951af9715c0 100644
> --- a/net/mac80211/aes_gmac.c
> +++ b/net/mac80211/aes_gmac.c
> @@ -25,16 +25,15 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 
> *aad, u8 *nonce,
>                        const u8 *data, size_t data_len, u8 *mic)
>  {
>         struct scatterlist sg[4];
> -       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;
>         u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
> +       struct aead_request *aead_req;
>
>         if (data_len < GMAC_MIC_LEN)
>                 return -EINVAL;
>
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         memset(zero, 0, GMAC_MIC_LEN);
>         sg_init_table(sg, 4);
> @@ -47,11 +46,11 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 
> *aad, u8 *nonce,
>         memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
>         iv[AES_BLOCK_SIZE - 1] = 0x01;
>
> -       aead_request_set_tfm(aead_req, tfm);
>         aead_request_set_crypt(aead_req, sg, sg, 0, iv);
>         aead_request_set_ad(aead_req, AAD_LEN + data_len);
>
>         crypto_aead_encrypt(aead_req);
> +       aead_request_free(aead_req);
>
>         return 0;
>  }
> diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
> index b48c1e13e281..2e366438f8ef 100644
> --- a/net/mac80211/wpa.c
> +++ b/net/mac80211/wpa.c
> @@ -461,10 +461,8 @@ 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);
> -       ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
> -                                 skb_put(skb, mic_len), mic_len);
> -
> -       return 0;
> +       return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
> +                                        skb_put(skb, mic_len), mic_len);
>  }
>
>
> @@ -696,10 +694,8 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data 
> *tx, struct sk_buff *skb)
>
>         pos += IEEE80211_GCMP_HDR_LEN;
>         gcmp_special_blocks(skb, pn, j_0, aad);
> -       ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
> -                                 skb_put(skb, IEEE80211_GCMP_MIC_LEN));
> -
> -       return 0;
> +       return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
> +                                        skb_put(skb, 
> IEEE80211_GCMP_MIC_LEN));
>  }
>
>  ieee80211_tx_result
> --
> 2.8.1
>

Reply via email to