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