0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/types.h>
0012 #include <linux/err.h>
0013 #include <linux/scatterlist.h>
0014 #include <crypto/aead.h>
0015
0016 #include "aead_api.h"
0017
0018 int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
0019 u8 *data, size_t data_len, u8 *mic)
0020 {
0021 size_t mic_len = crypto_aead_authsize(tfm);
0022 struct scatterlist sg[3];
0023 struct aead_request *aead_req;
0024 int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
0025 u8 *__aad;
0026 int ret;
0027
0028 aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
0029 if (!aead_req)
0030 return -ENOMEM;
0031
0032 __aad = (u8 *)aead_req + reqsize;
0033 memcpy(__aad, aad, aad_len);
0034
0035 sg_init_table(sg, 3);
0036 sg_set_buf(&sg[0], __aad, aad_len);
0037 sg_set_buf(&sg[1], data, data_len);
0038 sg_set_buf(&sg[2], mic, mic_len);
0039
0040 aead_request_set_tfm(aead_req, tfm);
0041 aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
0042 aead_request_set_ad(aead_req, sg[0].length);
0043
0044 ret = crypto_aead_encrypt(aead_req);
0045 kfree_sensitive(aead_req);
0046
0047 return ret;
0048 }
0049
0050 int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
0051 u8 *data, size_t data_len, u8 *mic)
0052 {
0053 size_t mic_len = crypto_aead_authsize(tfm);
0054 struct scatterlist sg[3];
0055 struct aead_request *aead_req;
0056 int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
0057 u8 *__aad;
0058 int err;
0059
0060 if (data_len == 0)
0061 return -EINVAL;
0062
0063 aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
0064 if (!aead_req)
0065 return -ENOMEM;
0066
0067 __aad = (u8 *)aead_req + reqsize;
0068 memcpy(__aad, aad, aad_len);
0069
0070 sg_init_table(sg, 3);
0071 sg_set_buf(&sg[0], __aad, aad_len);
0072 sg_set_buf(&sg[1], data, data_len);
0073 sg_set_buf(&sg[2], mic, mic_len);
0074
0075 aead_request_set_tfm(aead_req, tfm);
0076 aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
0077 aead_request_set_ad(aead_req, sg[0].length);
0078
0079 err = crypto_aead_decrypt(aead_req);
0080 kfree_sensitive(aead_req);
0081
0082 return err;
0083 }
0084
0085 struct crypto_aead *
0086 aead_key_setup_encrypt(const char *alg, const u8 key[],
0087 size_t key_len, size_t mic_len)
0088 {
0089 struct crypto_aead *tfm;
0090 int err;
0091
0092 tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
0093 if (IS_ERR(tfm))
0094 return tfm;
0095
0096 err = crypto_aead_setkey(tfm, key, key_len);
0097 if (err)
0098 goto free_aead;
0099 err = crypto_aead_setauthsize(tfm, mic_len);
0100 if (err)
0101 goto free_aead;
0102
0103 return tfm;
0104
0105 free_aead:
0106 crypto_free_aead(tfm);
0107 return ERR_PTR(err);
0108 }
0109
0110 void aead_key_free(struct crypto_aead *tfm)
0111 {
0112 crypto_free_aead(tfm);
0113 }