linux/net/mac80211/aead_api.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2003-2004, Instant802 Networks, Inc.
   4 * Copyright 2005-2006, Devicescape Software, Inc.
   5 * Copyright 2014-2015, Qualcomm Atheros, Inc.
   6 *
   7 * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/types.h>
  12#include <linux/err.h>
  13#include <linux/scatterlist.h>
  14#include <crypto/aead.h>
  15
  16#include "aead_api.h"
  17
  18int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
  19                 u8 *data, size_t data_len, u8 *mic)
  20{
  21        size_t mic_len = crypto_aead_authsize(tfm);
  22        struct scatterlist sg[3];
  23        struct aead_request *aead_req;
  24        int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
  25        u8 *__aad;
  26
  27        aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
  28        if (!aead_req)
  29                return -ENOMEM;
  30
  31        __aad = (u8 *)aead_req + reqsize;
  32        memcpy(__aad, aad, aad_len);
  33
  34        sg_init_table(sg, 3);
  35        sg_set_buf(&sg[0], __aad, aad_len);
  36        sg_set_buf(&sg[1], data, data_len);
  37        sg_set_buf(&sg[2], mic, mic_len);
  38
  39        aead_request_set_tfm(aead_req, tfm);
  40        aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
  41        aead_request_set_ad(aead_req, sg[0].length);
  42
  43        crypto_aead_encrypt(aead_req);
  44        kzfree(aead_req);
  45
  46        return 0;
  47}
  48
  49int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
  50                 u8 *data, size_t data_len, u8 *mic)
  51{
  52        size_t mic_len = crypto_aead_authsize(tfm);
  53        struct scatterlist sg[3];
  54        struct aead_request *aead_req;
  55        int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
  56        u8 *__aad;
  57        int err;
  58
  59        if (data_len == 0)
  60                return -EINVAL;
  61
  62        aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
  63        if (!aead_req)
  64                return -ENOMEM;
  65
  66        __aad = (u8 *)aead_req + reqsize;
  67        memcpy(__aad, aad, aad_len);
  68
  69        sg_init_table(sg, 3);
  70        sg_set_buf(&sg[0], __aad, aad_len);
  71        sg_set_buf(&sg[1], data, data_len);
  72        sg_set_buf(&sg[2], mic, mic_len);
  73
  74        aead_request_set_tfm(aead_req, tfm);
  75        aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
  76        aead_request_set_ad(aead_req, sg[0].length);
  77
  78        err = crypto_aead_decrypt(aead_req);
  79        kzfree(aead_req);
  80
  81        return err;
  82}
  83
  84struct crypto_aead *
  85aead_key_setup_encrypt(const char *alg, const u8 key[],
  86                       size_t key_len, size_t mic_len)
  87{
  88        struct crypto_aead *tfm;
  89        int err;
  90
  91        tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
  92        if (IS_ERR(tfm))
  93                return tfm;
  94
  95        err = crypto_aead_setkey(tfm, key, key_len);
  96        if (err)
  97                goto free_aead;
  98        err = crypto_aead_setauthsize(tfm, mic_len);
  99        if (err)
 100                goto free_aead;
 101
 102        return tfm;
 103
 104free_aead:
 105        crypto_free_aead(tfm);
 106        return ERR_PTR(err);
 107}
 108
 109void aead_key_free(struct crypto_aead *tfm)
 110{
 111        crypto_free_aead(tfm);
 112}
 113