1c9613335SNagadheeraj Rottela // SPDX-License-Identifier: GPL-2.0
2c9613335SNagadheeraj Rottela #include <linux/kernel.h>
3c9613335SNagadheeraj Rottela #include <linux/printk.h>
4c9613335SNagadheeraj Rottela #include <linux/crypto.h>
5c9613335SNagadheeraj Rottela #include <linux/rtnetlink.h>
6c9613335SNagadheeraj Rottela
7c9613335SNagadheeraj Rottela #include <crypto/aead.h>
8c9613335SNagadheeraj Rottela #include <crypto/authenc.h>
9c9613335SNagadheeraj Rottela #include <crypto/des.h>
10c9613335SNagadheeraj Rottela #include <crypto/internal/aead.h>
11c9613335SNagadheeraj Rottela #include <crypto/scatterwalk.h>
12c9613335SNagadheeraj Rottela #include <crypto/gcm.h>
13c9613335SNagadheeraj Rottela
14c9613335SNagadheeraj Rottela #include "nitrox_dev.h"
15c9613335SNagadheeraj Rottela #include "nitrox_common.h"
16c9613335SNagadheeraj Rottela #include "nitrox_req.h"
17c9613335SNagadheeraj Rottela
18c9613335SNagadheeraj Rottela #define GCM_AES_SALT_SIZE 4
19c9613335SNagadheeraj Rottela
20c9613335SNagadheeraj Rottela union gph_p3 {
21c9613335SNagadheeraj Rottela struct {
22c9613335SNagadheeraj Rottela #ifdef __BIG_ENDIAN_BITFIELD
23c9613335SNagadheeraj Rottela u16 iv_offset : 8;
24c9613335SNagadheeraj Rottela u16 auth_offset : 8;
25c9613335SNagadheeraj Rottela #else
26c9613335SNagadheeraj Rottela u16 auth_offset : 8;
27c9613335SNagadheeraj Rottela u16 iv_offset : 8;
28c9613335SNagadheeraj Rottela #endif
29c9613335SNagadheeraj Rottela };
30c9613335SNagadheeraj Rottela u16 param;
31c9613335SNagadheeraj Rottela };
32c9613335SNagadheeraj Rottela
nitrox_aes_gcm_setkey(struct crypto_aead * aead,const u8 * key,unsigned int keylen)33c9613335SNagadheeraj Rottela static int nitrox_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
34c9613335SNagadheeraj Rottela unsigned int keylen)
35c9613335SNagadheeraj Rottela {
36c9613335SNagadheeraj Rottela int aes_keylen;
37c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
38c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx;
39c9613335SNagadheeraj Rottela union fc_ctx_flags flags;
40c9613335SNagadheeraj Rottela
41c9613335SNagadheeraj Rottela aes_keylen = flexi_aes_keylen(keylen);
42674f368aSEric Biggers if (aes_keylen < 0)
43c9613335SNagadheeraj Rottela return -EINVAL;
44c9613335SNagadheeraj Rottela
45c9613335SNagadheeraj Rottela /* fill crypto context */
46c9613335SNagadheeraj Rottela fctx = nctx->u.fctx;
47cd078cb6SHerbert Xu flags.fu = be64_to_cpu(fctx->flags.f);
48c9613335SNagadheeraj Rottela flags.w0.aes_keylen = aes_keylen;
49cd078cb6SHerbert Xu fctx->flags.f = cpu_to_be64(flags.fu);
50c9613335SNagadheeraj Rottela
51c9613335SNagadheeraj Rottela /* copy enc key to context */
52c9613335SNagadheeraj Rottela memset(&fctx->crypto, 0, sizeof(fctx->crypto));
53c9613335SNagadheeraj Rottela memcpy(fctx->crypto.u.key, key, keylen);
54c9613335SNagadheeraj Rottela
55c9613335SNagadheeraj Rottela return 0;
56c9613335SNagadheeraj Rottela }
57c9613335SNagadheeraj Rottela
nitrox_aead_setauthsize(struct crypto_aead * aead,unsigned int authsize)58c9613335SNagadheeraj Rottela static int nitrox_aead_setauthsize(struct crypto_aead *aead,
59c9613335SNagadheeraj Rottela unsigned int authsize)
60c9613335SNagadheeraj Rottela {
61c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
62c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx;
63c9613335SNagadheeraj Rottela union fc_ctx_flags flags;
64c9613335SNagadheeraj Rottela
65cd078cb6SHerbert Xu flags.fu = be64_to_cpu(fctx->flags.f);
66c9613335SNagadheeraj Rottela flags.w0.mac_len = authsize;
67cd078cb6SHerbert Xu fctx->flags.f = cpu_to_be64(flags.fu);
68c9613335SNagadheeraj Rottela
69c9613335SNagadheeraj Rottela aead->authsize = authsize;
70c9613335SNagadheeraj Rottela
71c9613335SNagadheeraj Rottela return 0;
72c9613335SNagadheeraj Rottela }
73c9613335SNagadheeraj Rottela
nitrox_aes_gcm_setauthsize(struct crypto_aead * aead,unsigned int authsize)743fed9baaSNagadheeraj Rottela static int nitrox_aes_gcm_setauthsize(struct crypto_aead *aead,
753fed9baaSNagadheeraj Rottela unsigned int authsize)
763fed9baaSNagadheeraj Rottela {
773fed9baaSNagadheeraj Rottela switch (authsize) {
783fed9baaSNagadheeraj Rottela case 4:
793fed9baaSNagadheeraj Rottela case 8:
803fed9baaSNagadheeraj Rottela case 12:
813fed9baaSNagadheeraj Rottela case 13:
823fed9baaSNagadheeraj Rottela case 14:
833fed9baaSNagadheeraj Rottela case 15:
843fed9baaSNagadheeraj Rottela case 16:
853fed9baaSNagadheeraj Rottela break;
863fed9baaSNagadheeraj Rottela default:
873fed9baaSNagadheeraj Rottela return -EINVAL;
883fed9baaSNagadheeraj Rottela }
893fed9baaSNagadheeraj Rottela
903fed9baaSNagadheeraj Rottela return nitrox_aead_setauthsize(aead, authsize);
913fed9baaSNagadheeraj Rottela }
923fed9baaSNagadheeraj Rottela
alloc_src_sglist(struct nitrox_kcrypt_request * nkreq,struct scatterlist * src,char * iv,int ivsize,int buflen)938a3719a5SNagadheeraj Rottela static int alloc_src_sglist(struct nitrox_kcrypt_request *nkreq,
948a3719a5SNagadheeraj Rottela struct scatterlist *src, char *iv, int ivsize,
95c9613335SNagadheeraj Rottela int buflen)
96c9613335SNagadheeraj Rottela {
978a3719a5SNagadheeraj Rottela int nents = sg_nents_for_len(src, buflen);
98c9613335SNagadheeraj Rottela int ret;
99c9613335SNagadheeraj Rottela
100c9613335SNagadheeraj Rottela if (nents < 0)
101c9613335SNagadheeraj Rottela return nents;
102c9613335SNagadheeraj Rottela
1038a3719a5SNagadheeraj Rottela /* IV entry */
1048a3719a5SNagadheeraj Rottela nents += 1;
105c9613335SNagadheeraj Rottela /* Allocate buffer to hold IV and input scatterlist array */
106c9613335SNagadheeraj Rottela ret = alloc_src_req_buf(nkreq, nents, ivsize);
107c9613335SNagadheeraj Rottela if (ret)
108c9613335SNagadheeraj Rottela return ret;
109c9613335SNagadheeraj Rottela
110c9613335SNagadheeraj Rottela nitrox_creq_copy_iv(nkreq->src, iv, ivsize);
1118a3719a5SNagadheeraj Rottela nitrox_creq_set_src_sg(nkreq, nents, ivsize, src, buflen);
112c9613335SNagadheeraj Rottela
113c9613335SNagadheeraj Rottela return 0;
114c9613335SNagadheeraj Rottela }
115c9613335SNagadheeraj Rottela
alloc_dst_sglist(struct nitrox_kcrypt_request * nkreq,struct scatterlist * dst,int ivsize,int buflen)1168a3719a5SNagadheeraj Rottela static int alloc_dst_sglist(struct nitrox_kcrypt_request *nkreq,
1178a3719a5SNagadheeraj Rottela struct scatterlist *dst, int ivsize, int buflen)
118c9613335SNagadheeraj Rottela {
1198a3719a5SNagadheeraj Rottela int nents = sg_nents_for_len(dst, buflen);
120c9613335SNagadheeraj Rottela int ret;
121c9613335SNagadheeraj Rottela
122c9613335SNagadheeraj Rottela if (nents < 0)
123c9613335SNagadheeraj Rottela return nents;
124c9613335SNagadheeraj Rottela
1258a3719a5SNagadheeraj Rottela /* IV, ORH, COMPLETION entries */
1268a3719a5SNagadheeraj Rottela nents += 3;
127c9613335SNagadheeraj Rottela /* Allocate buffer to hold ORH, COMPLETION and output scatterlist
128c9613335SNagadheeraj Rottela * array
129c9613335SNagadheeraj Rottela */
130c9613335SNagadheeraj Rottela ret = alloc_dst_req_buf(nkreq, nents);
131c9613335SNagadheeraj Rottela if (ret)
132c9613335SNagadheeraj Rottela return ret;
133c9613335SNagadheeraj Rottela
134c9613335SNagadheeraj Rottela nitrox_creq_set_orh(nkreq);
135c9613335SNagadheeraj Rottela nitrox_creq_set_comp(nkreq);
1368a3719a5SNagadheeraj Rottela nitrox_creq_set_dst_sg(nkreq, nents, ivsize, dst, buflen);
137c9613335SNagadheeraj Rottela
138c9613335SNagadheeraj Rottela return 0;
139c9613335SNagadheeraj Rottela }
140c9613335SNagadheeraj Rottela
free_src_sglist(struct nitrox_kcrypt_request * nkreq)1418a3719a5SNagadheeraj Rottela static void free_src_sglist(struct nitrox_kcrypt_request *nkreq)
142c9613335SNagadheeraj Rottela {
143c9613335SNagadheeraj Rottela kfree(nkreq->src);
144c9613335SNagadheeraj Rottela }
145c9613335SNagadheeraj Rottela
free_dst_sglist(struct nitrox_kcrypt_request * nkreq)1468a3719a5SNagadheeraj Rottela static void free_dst_sglist(struct nitrox_kcrypt_request *nkreq)
147c9613335SNagadheeraj Rottela {
148c9613335SNagadheeraj Rottela kfree(nkreq->dst);
149c9613335SNagadheeraj Rottela }
150c9613335SNagadheeraj Rottela
nitrox_set_creq(struct nitrox_aead_rctx * rctx)1518a3719a5SNagadheeraj Rottela static int nitrox_set_creq(struct nitrox_aead_rctx *rctx)
152c9613335SNagadheeraj Rottela {
1538a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &rctx->nkreq.creq;
154c9613335SNagadheeraj Rottela union gph_p3 param3;
155c9613335SNagadheeraj Rottela int ret;
156c9613335SNagadheeraj Rottela
1578a3719a5SNagadheeraj Rottela creq->flags = rctx->flags;
1588a3719a5SNagadheeraj Rottela creq->gfp = (rctx->flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL :
1598a3719a5SNagadheeraj Rottela GFP_ATOMIC;
160c9613335SNagadheeraj Rottela
161c9613335SNagadheeraj Rottela creq->ctrl.value = 0;
162c9613335SNagadheeraj Rottela creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC;
1638a3719a5SNagadheeraj Rottela creq->ctrl.s.arg = rctx->ctrl_arg;
164c9613335SNagadheeraj Rottela
1658a3719a5SNagadheeraj Rottela creq->gph.param0 = cpu_to_be16(rctx->cryptlen);
1668a3719a5SNagadheeraj Rottela creq->gph.param1 = cpu_to_be16(rctx->cryptlen + rctx->assoclen);
1678a3719a5SNagadheeraj Rottela creq->gph.param2 = cpu_to_be16(rctx->ivsize + rctx->assoclen);
168c9613335SNagadheeraj Rottela param3.iv_offset = 0;
1698a3719a5SNagadheeraj Rottela param3.auth_offset = rctx->ivsize;
170c9613335SNagadheeraj Rottela creq->gph.param3 = cpu_to_be16(param3.param);
171c9613335SNagadheeraj Rottela
1728a3719a5SNagadheeraj Rottela creq->ctx_handle = rctx->ctx_handle;
173c9613335SNagadheeraj Rottela creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context);
174c9613335SNagadheeraj Rottela
1758a3719a5SNagadheeraj Rottela ret = alloc_src_sglist(&rctx->nkreq, rctx->src, rctx->iv, rctx->ivsize,
1768a3719a5SNagadheeraj Rottela rctx->srclen);
177c9613335SNagadheeraj Rottela if (ret)
178c9613335SNagadheeraj Rottela return ret;
179c9613335SNagadheeraj Rottela
1808a3719a5SNagadheeraj Rottela ret = alloc_dst_sglist(&rctx->nkreq, rctx->dst, rctx->ivsize,
1818a3719a5SNagadheeraj Rottela rctx->dstlen);
182c9613335SNagadheeraj Rottela if (ret) {
1838a3719a5SNagadheeraj Rottela free_src_sglist(&rctx->nkreq);
184c9613335SNagadheeraj Rottela return ret;
185c9613335SNagadheeraj Rottela }
186c9613335SNagadheeraj Rottela
187c9613335SNagadheeraj Rottela return 0;
188c9613335SNagadheeraj Rottela }
189c9613335SNagadheeraj Rottela
nitrox_aead_callback(void * arg,int err)190c9613335SNagadheeraj Rottela static void nitrox_aead_callback(void *arg, int err)
191c9613335SNagadheeraj Rottela {
192c9613335SNagadheeraj Rottela struct aead_request *areq = arg;
1938a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *rctx = aead_request_ctx(areq);
194c9613335SNagadheeraj Rottela
1958a3719a5SNagadheeraj Rottela free_src_sglist(&rctx->nkreq);
1968a3719a5SNagadheeraj Rottela free_dst_sglist(&rctx->nkreq);
197c9613335SNagadheeraj Rottela if (err) {
198c9613335SNagadheeraj Rottela pr_err_ratelimited("request failed status 0x%0x\n", err);
199c9613335SNagadheeraj Rottela err = -EINVAL;
200c9613335SNagadheeraj Rottela }
201c9613335SNagadheeraj Rottela
202*ea2fbe3bSHerbert Xu aead_request_complete(areq, err);
203c9613335SNagadheeraj Rottela }
204c9613335SNagadheeraj Rottela
nitrox_aes_gcm_assoclen_supported(unsigned int assoclen)2053fed9baaSNagadheeraj Rottela static inline bool nitrox_aes_gcm_assoclen_supported(unsigned int assoclen)
2063fed9baaSNagadheeraj Rottela {
2073fed9baaSNagadheeraj Rottela if (assoclen <= 512)
2083fed9baaSNagadheeraj Rottela return true;
2093fed9baaSNagadheeraj Rottela
2103fed9baaSNagadheeraj Rottela return false;
2113fed9baaSNagadheeraj Rottela }
2123fed9baaSNagadheeraj Rottela
nitrox_aes_gcm_enc(struct aead_request * areq)213c9613335SNagadheeraj Rottela static int nitrox_aes_gcm_enc(struct aead_request *areq)
214c9613335SNagadheeraj Rottela {
215c9613335SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq);
216c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
2178a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *rctx = aead_request_ctx(areq);
2188a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &rctx->nkreq.creq;
219c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx;
220c9613335SNagadheeraj Rottela int ret;
221c9613335SNagadheeraj Rottela
2223fed9baaSNagadheeraj Rottela if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen))
2233fed9baaSNagadheeraj Rottela return -EINVAL;
2243fed9baaSNagadheeraj Rottela
225c9613335SNagadheeraj Rottela memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE);
226c9613335SNagadheeraj Rottela
2278a3719a5SNagadheeraj Rottela rctx->cryptlen = areq->cryptlen;
2288a3719a5SNagadheeraj Rottela rctx->assoclen = areq->assoclen;
2298a3719a5SNagadheeraj Rottela rctx->srclen = areq->assoclen + areq->cryptlen;
2308a3719a5SNagadheeraj Rottela rctx->dstlen = rctx->srclen + aead->authsize;
2318a3719a5SNagadheeraj Rottela rctx->iv = &areq->iv[GCM_AES_SALT_SIZE];
2328a3719a5SNagadheeraj Rottela rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE;
2338a3719a5SNagadheeraj Rottela rctx->flags = areq->base.flags;
2348a3719a5SNagadheeraj Rottela rctx->ctx_handle = nctx->u.ctx_handle;
2358a3719a5SNagadheeraj Rottela rctx->src = areq->src;
2368a3719a5SNagadheeraj Rottela rctx->dst = areq->dst;
2378a3719a5SNagadheeraj Rottela rctx->ctrl_arg = ENCRYPT;
2388a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(rctx);
239c9613335SNagadheeraj Rottela if (ret)
240c9613335SNagadheeraj Rottela return ret;
241c9613335SNagadheeraj Rottela
242c9613335SNagadheeraj Rottela /* send the crypto request */
243c9613335SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback,
244c9613335SNagadheeraj Rottela areq);
245c9613335SNagadheeraj Rottela }
246c9613335SNagadheeraj Rottela
nitrox_aes_gcm_dec(struct aead_request * areq)247c9613335SNagadheeraj Rottela static int nitrox_aes_gcm_dec(struct aead_request *areq)
248c9613335SNagadheeraj Rottela {
249c9613335SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq);
250c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
2518a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *rctx = aead_request_ctx(areq);
2528a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &rctx->nkreq.creq;
253c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx;
254c9613335SNagadheeraj Rottela int ret;
255c9613335SNagadheeraj Rottela
2563fed9baaSNagadheeraj Rottela if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen))
2573fed9baaSNagadheeraj Rottela return -EINVAL;
2583fed9baaSNagadheeraj Rottela
259c9613335SNagadheeraj Rottela memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE);
260c9613335SNagadheeraj Rottela
2618a3719a5SNagadheeraj Rottela rctx->cryptlen = areq->cryptlen - aead->authsize;
2628a3719a5SNagadheeraj Rottela rctx->assoclen = areq->assoclen;
2638a3719a5SNagadheeraj Rottela rctx->srclen = areq->cryptlen + areq->assoclen;
2648a3719a5SNagadheeraj Rottela rctx->dstlen = rctx->srclen - aead->authsize;
2658a3719a5SNagadheeraj Rottela rctx->iv = &areq->iv[GCM_AES_SALT_SIZE];
2668a3719a5SNagadheeraj Rottela rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE;
2678a3719a5SNagadheeraj Rottela rctx->flags = areq->base.flags;
2688a3719a5SNagadheeraj Rottela rctx->ctx_handle = nctx->u.ctx_handle;
2698a3719a5SNagadheeraj Rottela rctx->src = areq->src;
2708a3719a5SNagadheeraj Rottela rctx->dst = areq->dst;
2718a3719a5SNagadheeraj Rottela rctx->ctrl_arg = DECRYPT;
2728a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(rctx);
273c9613335SNagadheeraj Rottela if (ret)
274c9613335SNagadheeraj Rottela return ret;
275c9613335SNagadheeraj Rottela
276c9613335SNagadheeraj Rottela /* send the crypto request */
277c9613335SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback,
278c9613335SNagadheeraj Rottela areq);
279c9613335SNagadheeraj Rottela }
280c9613335SNagadheeraj Rottela
nitrox_aead_init(struct crypto_aead * aead)281c9613335SNagadheeraj Rottela static int nitrox_aead_init(struct crypto_aead *aead)
282c9613335SNagadheeraj Rottela {
283c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
284c9613335SNagadheeraj Rottela struct crypto_ctx_hdr *chdr;
285c9613335SNagadheeraj Rottela
286c9613335SNagadheeraj Rottela /* get the first device */
287c9613335SNagadheeraj Rottela nctx->ndev = nitrox_get_first_device();
288c9613335SNagadheeraj Rottela if (!nctx->ndev)
289c9613335SNagadheeraj Rottela return -ENODEV;
290c9613335SNagadheeraj Rottela
291c9613335SNagadheeraj Rottela /* allocate nitrox crypto context */
292c9613335SNagadheeraj Rottela chdr = crypto_alloc_context(nctx->ndev);
293c9613335SNagadheeraj Rottela if (!chdr) {
294c9613335SNagadheeraj Rottela nitrox_put_device(nctx->ndev);
295c9613335SNagadheeraj Rottela return -ENOMEM;
296c9613335SNagadheeraj Rottela }
297c9613335SNagadheeraj Rottela nctx->chdr = chdr;
298c9613335SNagadheeraj Rottela nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr +
299c9613335SNagadheeraj Rottela sizeof(struct ctx_hdr));
300c9613335SNagadheeraj Rottela nctx->u.fctx->flags.f = 0;
301c9613335SNagadheeraj Rottela
302c9613335SNagadheeraj Rottela return 0;
303c9613335SNagadheeraj Rottela }
304c9613335SNagadheeraj Rottela
nitrox_gcm_common_init(struct crypto_aead * aead)3058a3719a5SNagadheeraj Rottela static int nitrox_gcm_common_init(struct crypto_aead *aead)
306c9613335SNagadheeraj Rottela {
307c9613335SNagadheeraj Rottela int ret;
308c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
309c9613335SNagadheeraj Rottela union fc_ctx_flags *flags;
310c9613335SNagadheeraj Rottela
311c9613335SNagadheeraj Rottela ret = nitrox_aead_init(aead);
312c9613335SNagadheeraj Rottela if (ret)
313c9613335SNagadheeraj Rottela return ret;
314c9613335SNagadheeraj Rottela
315c9613335SNagadheeraj Rottela flags = &nctx->u.fctx->flags;
316c9613335SNagadheeraj Rottela flags->w0.cipher_type = CIPHER_AES_GCM;
317c9613335SNagadheeraj Rottela flags->w0.hash_type = AUTH_NULL;
318c9613335SNagadheeraj Rottela flags->w0.iv_source = IV_FROM_DPTR;
319c9613335SNagadheeraj Rottela /* ask microcode to calculate ipad/opad */
320c9613335SNagadheeraj Rottela flags->w0.auth_input_type = 1;
321cd078cb6SHerbert Xu flags->f = cpu_to_be64(flags->fu);
322c9613335SNagadheeraj Rottela
3238a3719a5SNagadheeraj Rottela return 0;
3248a3719a5SNagadheeraj Rottela }
3258a3719a5SNagadheeraj Rottela
nitrox_aes_gcm_init(struct crypto_aead * aead)3268a3719a5SNagadheeraj Rottela static int nitrox_aes_gcm_init(struct crypto_aead *aead)
3278a3719a5SNagadheeraj Rottela {
3288a3719a5SNagadheeraj Rottela int ret;
3298a3719a5SNagadheeraj Rottela
3308a3719a5SNagadheeraj Rottela ret = nitrox_gcm_common_init(aead);
3318a3719a5SNagadheeraj Rottela if (ret)
3328a3719a5SNagadheeraj Rottela return ret;
3338a3719a5SNagadheeraj Rottela
3348a3719a5SNagadheeraj Rottela crypto_aead_set_reqsize(aead,
3358a3719a5SNagadheeraj Rottela sizeof(struct aead_request) +
3368a3719a5SNagadheeraj Rottela sizeof(struct nitrox_aead_rctx));
337c9613335SNagadheeraj Rottela
338c9613335SNagadheeraj Rottela return 0;
339c9613335SNagadheeraj Rottela }
340c9613335SNagadheeraj Rottela
nitrox_aead_exit(struct crypto_aead * aead)341c9613335SNagadheeraj Rottela static void nitrox_aead_exit(struct crypto_aead *aead)
342c9613335SNagadheeraj Rottela {
343c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
344c9613335SNagadheeraj Rottela
345c9613335SNagadheeraj Rottela /* free the nitrox crypto context */
346c9613335SNagadheeraj Rottela if (nctx->u.ctx_handle) {
347c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx;
348c9613335SNagadheeraj Rottela
349c9613335SNagadheeraj Rottela memzero_explicit(&fctx->crypto, sizeof(struct crypto_keys));
350c9613335SNagadheeraj Rottela memzero_explicit(&fctx->auth, sizeof(struct auth_keys));
351c9613335SNagadheeraj Rottela crypto_free_context((void *)nctx->chdr);
352c9613335SNagadheeraj Rottela }
353c9613335SNagadheeraj Rottela nitrox_put_device(nctx->ndev);
354c9613335SNagadheeraj Rottela
355c9613335SNagadheeraj Rottela nctx->u.ctx_handle = 0;
356c9613335SNagadheeraj Rottela nctx->ndev = NULL;
357c9613335SNagadheeraj Rottela }
358c9613335SNagadheeraj Rottela
nitrox_rfc4106_setkey(struct crypto_aead * aead,const u8 * key,unsigned int keylen)3598a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_setkey(struct crypto_aead *aead, const u8 *key,
3608a3719a5SNagadheeraj Rottela unsigned int keylen)
3618a3719a5SNagadheeraj Rottela {
3628a3719a5SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
3638a3719a5SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx;
3648a3719a5SNagadheeraj Rottela int ret;
3658a3719a5SNagadheeraj Rottela
3668a3719a5SNagadheeraj Rottela if (keylen < GCM_AES_SALT_SIZE)
3678a3719a5SNagadheeraj Rottela return -EINVAL;
3688a3719a5SNagadheeraj Rottela
3698a3719a5SNagadheeraj Rottela keylen -= GCM_AES_SALT_SIZE;
3708a3719a5SNagadheeraj Rottela ret = nitrox_aes_gcm_setkey(aead, key, keylen);
3718a3719a5SNagadheeraj Rottela if (ret)
3728a3719a5SNagadheeraj Rottela return ret;
3738a3719a5SNagadheeraj Rottela
3748a3719a5SNagadheeraj Rottela memcpy(fctx->crypto.iv, key + keylen, GCM_AES_SALT_SIZE);
3758a3719a5SNagadheeraj Rottela return 0;
3768a3719a5SNagadheeraj Rottela }
3778a3719a5SNagadheeraj Rottela
nitrox_rfc4106_setauthsize(struct crypto_aead * aead,unsigned int authsize)3788a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_setauthsize(struct crypto_aead *aead,
3798a3719a5SNagadheeraj Rottela unsigned int authsize)
3808a3719a5SNagadheeraj Rottela {
3818a3719a5SNagadheeraj Rottela switch (authsize) {
3828a3719a5SNagadheeraj Rottela case 8:
3838a3719a5SNagadheeraj Rottela case 12:
3848a3719a5SNagadheeraj Rottela case 16:
3858a3719a5SNagadheeraj Rottela break;
3868a3719a5SNagadheeraj Rottela default:
3878a3719a5SNagadheeraj Rottela return -EINVAL;
3888a3719a5SNagadheeraj Rottela }
3898a3719a5SNagadheeraj Rottela
3908a3719a5SNagadheeraj Rottela return nitrox_aead_setauthsize(aead, authsize);
3918a3719a5SNagadheeraj Rottela }
3928a3719a5SNagadheeraj Rottela
nitrox_rfc4106_set_aead_rctx_sglist(struct aead_request * areq)3938a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_set_aead_rctx_sglist(struct aead_request *areq)
3948a3719a5SNagadheeraj Rottela {
3951c64a7e1SHerbert Xu struct nitrox_rfc4106_rctx *rctx = aead_request_ctx_dma(areq);
3968a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *aead_rctx = &rctx->base;
3978a3719a5SNagadheeraj Rottela unsigned int assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE;
3988a3719a5SNagadheeraj Rottela struct scatterlist *sg;
3998a3719a5SNagadheeraj Rottela
4008a3719a5SNagadheeraj Rottela if (areq->assoclen != 16 && areq->assoclen != 20)
4018a3719a5SNagadheeraj Rottela return -EINVAL;
4028a3719a5SNagadheeraj Rottela
4038a3719a5SNagadheeraj Rottela scatterwalk_map_and_copy(rctx->assoc, areq->src, 0, assoclen, 0);
4048a3719a5SNagadheeraj Rottela sg_init_table(rctx->src, 3);
4058a3719a5SNagadheeraj Rottela sg_set_buf(rctx->src, rctx->assoc, assoclen);
4068a3719a5SNagadheeraj Rottela sg = scatterwalk_ffwd(rctx->src + 1, areq->src, areq->assoclen);
4078a3719a5SNagadheeraj Rottela if (sg != rctx->src + 1)
4088a3719a5SNagadheeraj Rottela sg_chain(rctx->src, 2, sg);
4098a3719a5SNagadheeraj Rottela
4108a3719a5SNagadheeraj Rottela if (areq->src != areq->dst) {
4118a3719a5SNagadheeraj Rottela sg_init_table(rctx->dst, 3);
4128a3719a5SNagadheeraj Rottela sg_set_buf(rctx->dst, rctx->assoc, assoclen);
4138a3719a5SNagadheeraj Rottela sg = scatterwalk_ffwd(rctx->dst + 1, areq->dst, areq->assoclen);
4148a3719a5SNagadheeraj Rottela if (sg != rctx->dst + 1)
4158a3719a5SNagadheeraj Rottela sg_chain(rctx->dst, 2, sg);
4168a3719a5SNagadheeraj Rottela }
4178a3719a5SNagadheeraj Rottela
4188a3719a5SNagadheeraj Rottela aead_rctx->src = rctx->src;
4198a3719a5SNagadheeraj Rottela aead_rctx->dst = (areq->src == areq->dst) ? rctx->src : rctx->dst;
4208a3719a5SNagadheeraj Rottela
4218a3719a5SNagadheeraj Rottela return 0;
4228a3719a5SNagadheeraj Rottela }
4238a3719a5SNagadheeraj Rottela
nitrox_rfc4106_callback(void * arg,int err)4248a3719a5SNagadheeraj Rottela static void nitrox_rfc4106_callback(void *arg, int err)
4258a3719a5SNagadheeraj Rottela {
4268a3719a5SNagadheeraj Rottela struct aead_request *areq = arg;
4271c64a7e1SHerbert Xu struct nitrox_rfc4106_rctx *rctx = aead_request_ctx_dma(areq);
4288a3719a5SNagadheeraj Rottela struct nitrox_kcrypt_request *nkreq = &rctx->base.nkreq;
4298a3719a5SNagadheeraj Rottela
4308a3719a5SNagadheeraj Rottela free_src_sglist(nkreq);
4318a3719a5SNagadheeraj Rottela free_dst_sglist(nkreq);
4328a3719a5SNagadheeraj Rottela if (err) {
4338a3719a5SNagadheeraj Rottela pr_err_ratelimited("request failed status 0x%0x\n", err);
4348a3719a5SNagadheeraj Rottela err = -EINVAL;
4358a3719a5SNagadheeraj Rottela }
4368a3719a5SNagadheeraj Rottela
437*ea2fbe3bSHerbert Xu aead_request_complete(areq, err);
4388a3719a5SNagadheeraj Rottela }
4398a3719a5SNagadheeraj Rottela
nitrox_rfc4106_enc(struct aead_request * areq)4408a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_enc(struct aead_request *areq)
4418a3719a5SNagadheeraj Rottela {
4428a3719a5SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq);
4438a3719a5SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
4441c64a7e1SHerbert Xu struct nitrox_rfc4106_rctx *rctx = aead_request_ctx_dma(areq);
4458a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *aead_rctx = &rctx->base;
4468a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &aead_rctx->nkreq.creq;
4478a3719a5SNagadheeraj Rottela int ret;
4488a3719a5SNagadheeraj Rottela
4498a3719a5SNagadheeraj Rottela aead_rctx->cryptlen = areq->cryptlen;
4508a3719a5SNagadheeraj Rottela aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE;
4518a3719a5SNagadheeraj Rottela aead_rctx->srclen = aead_rctx->assoclen + aead_rctx->cryptlen;
4528a3719a5SNagadheeraj Rottela aead_rctx->dstlen = aead_rctx->srclen + aead->authsize;
4538a3719a5SNagadheeraj Rottela aead_rctx->iv = areq->iv;
4548a3719a5SNagadheeraj Rottela aead_rctx->ivsize = GCM_RFC4106_IV_SIZE;
4558a3719a5SNagadheeraj Rottela aead_rctx->flags = areq->base.flags;
4568a3719a5SNagadheeraj Rottela aead_rctx->ctx_handle = nctx->u.ctx_handle;
4578a3719a5SNagadheeraj Rottela aead_rctx->ctrl_arg = ENCRYPT;
4588a3719a5SNagadheeraj Rottela
4598a3719a5SNagadheeraj Rottela ret = nitrox_rfc4106_set_aead_rctx_sglist(areq);
4608a3719a5SNagadheeraj Rottela if (ret)
4618a3719a5SNagadheeraj Rottela return ret;
4628a3719a5SNagadheeraj Rottela
4638a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(aead_rctx);
4648a3719a5SNagadheeraj Rottela if (ret)
4658a3719a5SNagadheeraj Rottela return ret;
4668a3719a5SNagadheeraj Rottela
4678a3719a5SNagadheeraj Rottela /* send the crypto request */
4688a3719a5SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq,
4698a3719a5SNagadheeraj Rottela nitrox_rfc4106_callback, areq);
4708a3719a5SNagadheeraj Rottela }
4718a3719a5SNagadheeraj Rottela
nitrox_rfc4106_dec(struct aead_request * areq)4728a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_dec(struct aead_request *areq)
4738a3719a5SNagadheeraj Rottela {
4748a3719a5SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq);
4751c64a7e1SHerbert Xu struct nitrox_crypto_ctx *nctx = crypto_aead_ctx_dma(aead);
4768a3719a5SNagadheeraj Rottela struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq);
4778a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *aead_rctx = &rctx->base;
4788a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &aead_rctx->nkreq.creq;
4798a3719a5SNagadheeraj Rottela int ret;
4808a3719a5SNagadheeraj Rottela
4818a3719a5SNagadheeraj Rottela aead_rctx->cryptlen = areq->cryptlen - aead->authsize;
4828a3719a5SNagadheeraj Rottela aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE;
4838a3719a5SNagadheeraj Rottela aead_rctx->srclen =
4848a3719a5SNagadheeraj Rottela areq->cryptlen - GCM_RFC4106_IV_SIZE + areq->assoclen;
4858a3719a5SNagadheeraj Rottela aead_rctx->dstlen = aead_rctx->srclen - aead->authsize;
4868a3719a5SNagadheeraj Rottela aead_rctx->iv = areq->iv;
4878a3719a5SNagadheeraj Rottela aead_rctx->ivsize = GCM_RFC4106_IV_SIZE;
4888a3719a5SNagadheeraj Rottela aead_rctx->flags = areq->base.flags;
4898a3719a5SNagadheeraj Rottela aead_rctx->ctx_handle = nctx->u.ctx_handle;
4908a3719a5SNagadheeraj Rottela aead_rctx->ctrl_arg = DECRYPT;
4918a3719a5SNagadheeraj Rottela
4928a3719a5SNagadheeraj Rottela ret = nitrox_rfc4106_set_aead_rctx_sglist(areq);
4938a3719a5SNagadheeraj Rottela if (ret)
4948a3719a5SNagadheeraj Rottela return ret;
4958a3719a5SNagadheeraj Rottela
4968a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(aead_rctx);
4978a3719a5SNagadheeraj Rottela if (ret)
4988a3719a5SNagadheeraj Rottela return ret;
4998a3719a5SNagadheeraj Rottela
5008a3719a5SNagadheeraj Rottela /* send the crypto request */
5018a3719a5SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq,
5028a3719a5SNagadheeraj Rottela nitrox_rfc4106_callback, areq);
5038a3719a5SNagadheeraj Rottela }
5048a3719a5SNagadheeraj Rottela
nitrox_rfc4106_init(struct crypto_aead * aead)5058a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_init(struct crypto_aead *aead)
5068a3719a5SNagadheeraj Rottela {
5078a3719a5SNagadheeraj Rottela int ret;
5088a3719a5SNagadheeraj Rottela
5098a3719a5SNagadheeraj Rottela ret = nitrox_gcm_common_init(aead);
5108a3719a5SNagadheeraj Rottela if (ret)
5118a3719a5SNagadheeraj Rottela return ret;
5128a3719a5SNagadheeraj Rottela
5131c64a7e1SHerbert Xu crypto_aead_set_reqsize_dma(aead, sizeof(struct aead_request) +
5148a3719a5SNagadheeraj Rottela sizeof(struct nitrox_rfc4106_rctx));
5158a3719a5SNagadheeraj Rottela
5168a3719a5SNagadheeraj Rottela return 0;
5178a3719a5SNagadheeraj Rottela }
5188a3719a5SNagadheeraj Rottela
519c9613335SNagadheeraj Rottela static struct aead_alg nitrox_aeads[] = { {
520c9613335SNagadheeraj Rottela .base = {
521c9613335SNagadheeraj Rottela .cra_name = "gcm(aes)",
522c9613335SNagadheeraj Rottela .cra_driver_name = "n5_aes_gcm",
523c9613335SNagadheeraj Rottela .cra_priority = PRIO,
524b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
5253fed9baaSNagadheeraj Rottela .cra_blocksize = 1,
526c9613335SNagadheeraj Rottela .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
527c9613335SNagadheeraj Rottela .cra_alignmask = 0,
528c9613335SNagadheeraj Rottela .cra_module = THIS_MODULE,
529c9613335SNagadheeraj Rottela },
530c9613335SNagadheeraj Rottela .setkey = nitrox_aes_gcm_setkey,
5313fed9baaSNagadheeraj Rottela .setauthsize = nitrox_aes_gcm_setauthsize,
532c9613335SNagadheeraj Rottela .encrypt = nitrox_aes_gcm_enc,
533c9613335SNagadheeraj Rottela .decrypt = nitrox_aes_gcm_dec,
534c9613335SNagadheeraj Rottela .init = nitrox_aes_gcm_init,
535c9613335SNagadheeraj Rottela .exit = nitrox_aead_exit,
536c9613335SNagadheeraj Rottela .ivsize = GCM_AES_IV_SIZE,
537c9613335SNagadheeraj Rottela .maxauthsize = AES_BLOCK_SIZE,
5388a3719a5SNagadheeraj Rottela }, {
5398a3719a5SNagadheeraj Rottela .base = {
5408a3719a5SNagadheeraj Rottela .cra_name = "rfc4106(gcm(aes))",
5418a3719a5SNagadheeraj Rottela .cra_driver_name = "n5_rfc4106",
5428a3719a5SNagadheeraj Rottela .cra_priority = PRIO,
543b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
5443fed9baaSNagadheeraj Rottela .cra_blocksize = 1,
5458a3719a5SNagadheeraj Rottela .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
5468a3719a5SNagadheeraj Rottela .cra_alignmask = 0,
5478a3719a5SNagadheeraj Rottela .cra_module = THIS_MODULE,
5488a3719a5SNagadheeraj Rottela },
5498a3719a5SNagadheeraj Rottela .setkey = nitrox_rfc4106_setkey,
5508a3719a5SNagadheeraj Rottela .setauthsize = nitrox_rfc4106_setauthsize,
5518a3719a5SNagadheeraj Rottela .encrypt = nitrox_rfc4106_enc,
5528a3719a5SNagadheeraj Rottela .decrypt = nitrox_rfc4106_dec,
5538a3719a5SNagadheeraj Rottela .init = nitrox_rfc4106_init,
5548a3719a5SNagadheeraj Rottela .exit = nitrox_aead_exit,
5558a3719a5SNagadheeraj Rottela .ivsize = GCM_RFC4106_IV_SIZE,
5568a3719a5SNagadheeraj Rottela .maxauthsize = AES_BLOCK_SIZE,
557c9613335SNagadheeraj Rottela } };
558c9613335SNagadheeraj Rottela
nitrox_register_aeads(void)559c9613335SNagadheeraj Rottela int nitrox_register_aeads(void)
560c9613335SNagadheeraj Rottela {
561c9613335SNagadheeraj Rottela return crypto_register_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads));
562c9613335SNagadheeraj Rottela }
563c9613335SNagadheeraj Rottela
nitrox_unregister_aeads(void)564c9613335SNagadheeraj Rottela void nitrox_unregister_aeads(void)
565c9613335SNagadheeraj Rottela {
566c9613335SNagadheeraj Rottela crypto_unregister_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads));
567c9613335SNagadheeraj Rottela }
568