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        int ret;
  27
  28        aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
  29        if (!aead_req)
  30                return -ENOMEM;
  31
  32        __aad = (u8 *)aead_req + reqsize;
  33        memcpy(__aad, aad, aad_len);
  34
  35        sg_init_table(sg, 3);
  36        sg_set_buf(&sg[0], __aad, aad_len);
  37        sg_set_buf(&sg[1], data, data_len);
  38        sg_set_buf(&sg[2], mic, mic_len);
  39
  40        aead_request_set_tfm(aead_req, tfm);
  41        aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
  42        aead_request_set_ad(aead_req, sg[0].length);
  43
  44        ret = crypto_aead_encrypt(aead_req);
  45        kfree_sensitive(aead_req);
  46
  47        return ret;
  48}
  49
  50int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
  51                 u8 *data, size_t data_len, u8 *mic)
  52{
  53        size_t mic_len = crypto_aead_authsize(tfm);
  54        struct scatterlist sg[3];
  55        struct aead_request *aead_req;
  56        int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
  57        u8 *__aad;
  58        int err;
  59
  60        if (data_len == 0)
  61                return -EINVAL;
  62
  63        aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
  64        if (!aead_req)
  65                return -ENOMEM;
  66
  67        __aad = (u8 *)aead_req + reqsize;
  68        memcpy(__aad, aad, aad_len);
  69
  70        sg_init_table(sg, 3);
  71        sg_set_buf(&sg[0], __aad, aad_len);
  72        sg_set_buf(&sg[1], data, data_len);
  73        sg_set_buf(&sg[2], mic, mic_len);
  74
  75        aead_request_set_tfm(aead_req, tfm);
  76        aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
  77        aead_request_set_ad(aead_req, sg[0].length);
  78
  79        err = crypto_aead_decrypt(aead_req);
  80        kfree_sensitive(aead_req);
  81
  82        return err;
  83}
  84
  85struct crypto_aead *
  86aead_key_setup_encrypt(const char *alg, const u8 key[],
  87                       size_t key_len, size_t mic_len)
  88{
  89        struct crypto_aead *tfm;
  90        int err;
  91
  92        tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
  93        if (IS_ERR(tfm))
  94                return tfm;
  95
  96        err = crypto_aead_setkey(tfm, key, key_len);
  97        if (err)
  98                goto free_aead;
  99        err = crypto_aead_setauthsize(tfm, mic_len);
 100        if (err)
 101                goto free_aead;
 102
 103        return tfm;
 104
 105free_aead:
 106        crypto_free_aead(tfm);
 107        return ERR_PTR(err);
 108}
 109
 110void aead_key_free(struct crypto_aead *tfm)
 111{
 112        crypto_free_aead(tfm);
 113}
 114