Lines Matching +full:gxl +full:- +full:crypto

1 // SPDX-License-Identifier: GPL-2.0
3 * amlogic-cipher.c - hardware cryptographic offloader for Amlogic GXL SoC
5 * Copyright (C) 2018-2019 Corentin LABBE <[email protected]>
11 #include <linux/crypto.h>
14 #include <crypto/scatterwalk.h>
16 #include <linux/dma-mapping.h>
17 #include <crypto/internal/skcipher.h>
18 #include "amlogic-gxl.h"
22 return atomic_inc_return(&mc->flow) % MAXFLOW; in get_engine_number()
27 struct scatterlist *src_sg = areq->src; in meson_cipher_need_fallback()
28 struct scatterlist *dst_sg = areq->dst; in meson_cipher_need_fallback()
30 if (areq->cryptlen == 0) in meson_cipher_need_fallback()
37 if (sg_nents(src_sg) > MAXDESC - 3 || sg_nents(dst_sg) > MAXDESC - 3) in meson_cipher_need_fallback()
41 if ((src_sg->length % 16) != 0) in meson_cipher_need_fallback()
43 if ((dst_sg->length % 16) != 0) in meson_cipher_need_fallback()
45 if (src_sg->length != dst_sg->length) in meson_cipher_need_fallback()
47 if (!IS_ALIGNED(src_sg->offset, sizeof(u32))) in meson_cipher_need_fallback()
49 if (!IS_ALIGNED(dst_sg->offset, sizeof(u32))) in meson_cipher_need_fallback()
69 algt->stat_fb++; in meson_cipher_do_fallback()
71 skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); in meson_cipher_do_fallback()
72 skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, in meson_cipher_do_fallback()
73 areq->base.complete, areq->base.data); in meson_cipher_do_fallback()
74 skcipher_request_set_crypt(&rctx->fallback_req, areq->src, areq->dst, in meson_cipher_do_fallback()
75 areq->cryptlen, areq->iv); in meson_cipher_do_fallback()
77 if (rctx->op_dir == MESON_DECRYPT) in meson_cipher_do_fallback()
78 err = crypto_skcipher_decrypt(&rctx->fallback_req); in meson_cipher_do_fallback()
80 err = crypto_skcipher_encrypt(&rctx->fallback_req); in meson_cipher_do_fallback()
89 struct meson_dev *mc = op->mc; in meson_cipher()
92 int flow = rctx->flow; in meson_cipher()
94 struct scatterlist *src_sg = areq->src; in meson_cipher()
95 struct scatterlist *dst_sg = areq->dst; in meson_cipher()
106 dev_dbg(mc->dev, "%s %s %u %x IV(%u) key=%u flow=%d\n", __func__, in meson_cipher()
107 crypto_tfm_alg_name(areq->base.tfm), in meson_cipher()
108 areq->cryptlen, in meson_cipher()
109 rctx->op_dir, crypto_skcipher_ivsize(tfm), in meson_cipher()
110 op->keylen, flow); in meson_cipher()
113 algt->stat_req++; in meson_cipher()
114 mc->chanlist[flow].stat_req++; in meson_cipher()
124 return -ENOMEM; in meson_cipher()
126 memcpy(bkeyiv, op->key, op->keylen); in meson_cipher()
127 keyivlen = op->keylen; in meson_cipher()
130 if (areq->iv && ivsize > 0) { in meson_cipher()
131 if (ivsize > areq->cryptlen) { in meson_cipher()
132 dev_err(mc->dev, "invalid ivsize=%d vs len=%d\n", ivsize, areq->cryptlen); in meson_cipher()
133 err = -EINVAL; in meson_cipher()
136 memcpy(bkeyiv + 32, areq->iv, ivsize); in meson_cipher()
138 if (rctx->op_dir == MESON_DECRYPT) { in meson_cipher()
141 err = -ENOMEM; in meson_cipher()
144 offset = areq->cryptlen - ivsize; in meson_cipher()
145 scatterwalk_map_and_copy(backup_iv, areq->src, offset, in meson_cipher()
152 phykeyiv = dma_map_single(mc->dev, bkeyiv, keyivlen, in meson_cipher()
154 err = dma_mapping_error(mc->dev, phykeyiv); in meson_cipher()
156 dev_err(mc->dev, "Cannot DMA MAP KEY IV\n"); in meson_cipher()
164 desc = &mc->chanlist[flow].tl[tloffset]; in meson_cipher()
166 todo = min(keyivlen - eat, 16u); in meson_cipher()
167 desc->t_src = cpu_to_le32(phykeyiv + i * 16); in meson_cipher()
168 desc->t_dst = cpu_to_le32(i * 16); in meson_cipher()
170 desc->t_status = cpu_to_le32(v); in meson_cipher()
177 if (areq->src == areq->dst) { in meson_cipher()
178 nr_sgs = dma_map_sg(mc->dev, areq->src, sg_nents(areq->src), in meson_cipher()
181 dev_err(mc->dev, "Invalid SG count %d\n", nr_sgs); in meson_cipher()
182 err = -EINVAL; in meson_cipher()
187 nr_sgs = dma_map_sg(mc->dev, areq->src, sg_nents(areq->src), in meson_cipher()
189 if (!nr_sgs || nr_sgs > MAXDESC - 3) { in meson_cipher()
190 dev_err(mc->dev, "Invalid SG count %d\n", nr_sgs); in meson_cipher()
191 err = -EINVAL; in meson_cipher()
194 nr_sgd = dma_map_sg(mc->dev, areq->dst, sg_nents(areq->dst), in meson_cipher()
196 if (!nr_sgd || nr_sgd > MAXDESC - 3) { in meson_cipher()
197 dev_err(mc->dev, "Invalid SG count %d\n", nr_sgd); in meson_cipher()
198 err = -EINVAL; in meson_cipher()
203 src_sg = areq->src; in meson_cipher()
204 dst_sg = areq->dst; in meson_cipher()
205 len = areq->cryptlen; in meson_cipher()
207 desc = &mc->chanlist[flow].tl[tloffset]; in meson_cipher()
210 desc->t_src = cpu_to_le32(sg_dma_address(src_sg)); in meson_cipher()
211 desc->t_dst = cpu_to_le32(sg_dma_address(dst_sg)); in meson_cipher()
213 v = (op->keymode << 20) | DESC_OWN | todo | (algt->blockmode << 26); in meson_cipher()
214 if (rctx->op_dir) in meson_cipher()
216 len -= todo; in meson_cipher()
220 desc->t_status = cpu_to_le32(v); in meson_cipher()
226 reinit_completion(&mc->chanlist[flow].complete); in meson_cipher()
227 mc->chanlist[flow].status = 0; in meson_cipher()
228 writel(mc->chanlist[flow].t_phy | 2, mc->base + (flow << 2)); in meson_cipher()
229 wait_for_completion_interruptible_timeout(&mc->chanlist[flow].complete, in meson_cipher()
231 if (mc->chanlist[flow].status == 0) { in meson_cipher()
232 dev_err(mc->dev, "DMA timeout for flow %d\n", flow); in meson_cipher()
233 err = -EINVAL; in meson_cipher()
236 dma_unmap_single(mc->dev, phykeyiv, keyivlen, DMA_TO_DEVICE); in meson_cipher()
238 if (areq->src == areq->dst) { in meson_cipher()
239 dma_unmap_sg(mc->dev, areq->src, sg_nents(areq->src), DMA_BIDIRECTIONAL); in meson_cipher()
241 dma_unmap_sg(mc->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); in meson_cipher()
242 dma_unmap_sg(mc->dev, areq->dst, sg_nents(areq->dst), DMA_FROM_DEVICE); in meson_cipher()
245 if (areq->iv && ivsize > 0) { in meson_cipher()
246 if (rctx->op_dir == MESON_DECRYPT) { in meson_cipher()
247 memcpy(areq->iv, backup_iv, ivsize); in meson_cipher()
249 scatterwalk_map_and_copy(areq->iv, areq->dst, in meson_cipher()
250 areq->cryptlen - ivsize, in meson_cipher()
282 rctx->op_dir = MESON_DECRYPT; in meson_skdecrypt()
285 e = get_engine_number(op->mc); in meson_skdecrypt()
286 engine = op->mc->chanlist[e].engine; in meson_skdecrypt()
287 rctx->flow = e; in meson_skdecrypt()
300 rctx->op_dir = MESON_ENCRYPT; in meson_skencrypt()
303 e = get_engine_number(op->mc); in meson_skencrypt()
304 engine = op->mc->chanlist[e].engine; in meson_skencrypt()
305 rctx->flow = e; in meson_skencrypt()
321 op->mc = algt->mc; in meson_cipher_init()
323 op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); in meson_cipher_init()
324 if (IS_ERR(op->fallback_tfm)) { in meson_cipher_init()
325 dev_err(op->mc->dev, "ERROR: Cannot allocate fallback for %s %ld\n", in meson_cipher_init()
326 name, PTR_ERR(op->fallback_tfm)); in meson_cipher_init()
327 return PTR_ERR(op->fallback_tfm); in meson_cipher_init()
331 crypto_skcipher_reqsize(op->fallback_tfm)); in meson_cipher_init()
340 kfree_sensitive(op->key); in meson_cipher_exit()
341 crypto_free_skcipher(op->fallback_tfm); in meson_cipher_exit()
348 struct meson_dev *mc = op->mc; in meson_aes_setkey()
352 op->keymode = MODE_AES_128; in meson_aes_setkey()
355 op->keymode = MODE_AES_192; in meson_aes_setkey()
358 op->keymode = MODE_AES_256; in meson_aes_setkey()
361 dev_dbg(mc->dev, "ERROR: Invalid keylen %u\n", keylen); in meson_aes_setkey()
362 return -EINVAL; in meson_aes_setkey()
364 kfree_sensitive(op->key); in meson_aes_setkey()
365 op->keylen = keylen; in meson_aes_setkey()
366 op->key = kmemdup(key, keylen, GFP_KERNEL | GFP_DMA); in meson_aes_setkey()
367 if (!op->key) in meson_aes_setkey()
368 return -ENOMEM; in meson_aes_setkey()
370 return crypto_skcipher_setkey(op->fallback_tfm, key, keylen); in meson_aes_setkey()