Linux 6.10-rc3
[linux-block.git] / net / mac80211 / aead_api.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
f0706e82
JB
2/*
3 * Copyright 2003-2004, Instant802 Networks, Inc.
4 * Copyright 2005-2006, Devicescape Software, Inc.
4133da73 5 * Copyright 2014-2015, Qualcomm Atheros, Inc.
f0706e82 6 *
7ec7c4a9 7 * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
f0706e82
JB
8 */
9
172589cc 10#include <linux/kernel.h>
f0706e82 11#include <linux/types.h>
f0706e82 12#include <linux/err.h>
4133da73 13#include <linux/scatterlist.h>
d8fe0ddd 14#include <crypto/aead.h>
f0706e82 15
4133da73 16#include "aead_api.h"
f0706e82 17
4133da73
XG
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)
f0706e82 20{
9e97964d 21 size_t mic_len = crypto_aead_authsize(tfm);
957e0fe6 22 struct scatterlist sg[3];
f4a067f9
AB
23 struct aead_request *aead_req;
24 int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
25 u8 *__aad;
58d25626 26 int ret;
f0706e82 27
4133da73 28 aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
f4a067f9
AB
29 if (!aead_req)
30 return -ENOMEM;
6e1ee5d2 31
f4a067f9 32 __aad = (u8 *)aead_req + reqsize;
4133da73 33 memcpy(__aad, aad, aad_len);
f0706e82 34
957e0fe6 35 sg_init_table(sg, 3);
4133da73 36 sg_set_buf(&sg[0], __aad, aad_len);
957e0fe6
HX
37 sg_set_buf(&sg[1], data, data_len);
38 sg_set_buf(&sg[2], mic, mic_len);
f0706e82 39
6e1ee5d2 40 aead_request_set_tfm(aead_req, tfm);
957e0fe6
HX
41 aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
42 aead_request_set_ad(aead_req, sg[0].length);
f0706e82 43
58d25626 44 ret = crypto_aead_encrypt(aead_req);
453431a5 45 kfree_sensitive(aead_req);
f4a067f9 46
58d25626 47 return ret;
f0706e82
JB
48}
49
4133da73
XG
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)
f0706e82 52{
9e97964d 53 size_t mic_len = crypto_aead_authsize(tfm);
957e0fe6 54 struct scatterlist sg[3];
f4a067f9
AB
55 struct aead_request *aead_req;
56 int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
57 u8 *__aad;
58 int err;
7ec7c4a9 59
4f031fa9
RW
60 if (data_len == 0)
61 return -EINVAL;
62
4133da73 63 aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
f4a067f9
AB
64 if (!aead_req)
65 return -ENOMEM;
66
67 __aad = (u8 *)aead_req + reqsize;
4133da73 68 memcpy(__aad, aad, aad_len);
7ec7c4a9 69
957e0fe6 70 sg_init_table(sg, 3);
4133da73 71 sg_set_buf(&sg[0], __aad, aad_len);
957e0fe6
HX
72 sg_set_buf(&sg[1], data, data_len);
73 sg_set_buf(&sg[2], mic, mic_len);
7ec7c4a9 74
6e1ee5d2 75 aead_request_set_tfm(aead_req, tfm);
957e0fe6
HX
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);
7ec7c4a9 78
f4a067f9 79 err = crypto_aead_decrypt(aead_req);
453431a5 80 kfree_sensitive(aead_req);
f4a067f9
AB
81
82 return err;
f0706e82
JB
83}
84
4133da73
XG
85struct crypto_aead *
86aead_key_setup_encrypt(const char *alg, const u8 key[],
87 size_t key_len, size_t mic_len)
f0706e82 88{
7ec7c4a9
AB
89 struct crypto_aead *tfm;
90 int err;
f0706e82 91
4133da73 92 tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
7ec7c4a9
AB
93 if (IS_ERR(tfm))
94 return tfm;
f0706e82 95
2b2ba0db 96 err = crypto_aead_setkey(tfm, key, key_len);
45fd6329
DC
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;
f0706e82 104
45fd6329 105free_aead:
7ec7c4a9
AB
106 crypto_free_aead(tfm);
107 return ERR_PTR(err);
f0706e82
JB
108}
109
4133da73 110void aead_key_free(struct crypto_aead *tfm)
f0706e82 111{
7ec7c4a9 112 crypto_free_aead(tfm);
f0706e82 113}