1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Cipher algorithms supported by the CESA: DES, 3DES and AES. |
4 | * |
5 | * Author: Boris Brezillon <boris.brezillon@free-electrons.com> |
6 | * Author: Arnaud Ebalard <arno@natisbad.org> |
7 | * |
8 | * This work is based on an initial version written by |
9 | * Sebastian Andrzej Siewior < sebastian at breakpoint dot cc > |
10 | */ |
11 | |
12 | #include <crypto/aes.h> |
13 | #include <crypto/internal/des.h> |
14 | #include <linux/device.h> |
15 | #include <linux/dma-mapping.h> |
16 | |
17 | #include "cesa.h" |
18 | |
19 | struct mv_cesa_des_ctx { |
20 | struct mv_cesa_ctx base; |
21 | u8 key[DES_KEY_SIZE]; |
22 | }; |
23 | |
24 | struct mv_cesa_des3_ctx { |
25 | struct mv_cesa_ctx base; |
26 | u8 key[DES3_EDE_KEY_SIZE]; |
27 | }; |
28 | |
29 | struct mv_cesa_aes_ctx { |
30 | struct mv_cesa_ctx base; |
31 | struct crypto_aes_ctx aes; |
32 | }; |
33 | |
34 | struct mv_cesa_skcipher_dma_iter { |
35 | struct mv_cesa_dma_iter base; |
36 | struct mv_cesa_sg_dma_iter src; |
37 | struct mv_cesa_sg_dma_iter dst; |
38 | }; |
39 | |
40 | static inline void |
41 | mv_cesa_skcipher_req_iter_init(struct mv_cesa_skcipher_dma_iter *iter, |
42 | struct skcipher_request *req) |
43 | { |
44 | mv_cesa_req_dma_iter_init(iter: &iter->base, len: req->cryptlen); |
45 | mv_cesa_sg_dma_iter_init(iter: &iter->src, sg: req->src, dir: DMA_TO_DEVICE); |
46 | mv_cesa_sg_dma_iter_init(iter: &iter->dst, sg: req->dst, dir: DMA_FROM_DEVICE); |
47 | } |
48 | |
49 | static inline bool |
50 | mv_cesa_skcipher_req_iter_next_op(struct mv_cesa_skcipher_dma_iter *iter) |
51 | { |
52 | iter->src.op_offset = 0; |
53 | iter->dst.op_offset = 0; |
54 | |
55 | return mv_cesa_req_dma_iter_next_op(iter: &iter->base); |
56 | } |
57 | |
58 | static inline void |
59 | mv_cesa_skcipher_dma_cleanup(struct skcipher_request *req) |
60 | { |
61 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
62 | |
63 | if (req->dst != req->src) { |
64 | dma_unmap_sg(cesa_dev->dev, req->dst, creq->dst_nents, |
65 | DMA_FROM_DEVICE); |
66 | dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, |
67 | DMA_TO_DEVICE); |
68 | } else { |
69 | dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, |
70 | DMA_BIDIRECTIONAL); |
71 | } |
72 | mv_cesa_dma_cleanup(dreq: &creq->base); |
73 | } |
74 | |
75 | static inline void mv_cesa_skcipher_cleanup(struct skcipher_request *req) |
76 | { |
77 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
78 | |
79 | if (mv_cesa_req_get_type(req: &creq->base) == CESA_DMA_REQ) |
80 | mv_cesa_skcipher_dma_cleanup(req); |
81 | } |
82 | |
83 | static void mv_cesa_skcipher_std_step(struct skcipher_request *req) |
84 | { |
85 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
86 | struct mv_cesa_skcipher_std_req *sreq = &creq->std; |
87 | struct mv_cesa_engine *engine = creq->base.engine; |
88 | size_t len = min_t(size_t, req->cryptlen - sreq->offset, |
89 | CESA_SA_SRAM_PAYLOAD_SIZE); |
90 | |
91 | mv_cesa_adjust_op(engine, op: &sreq->op); |
92 | if (engine->pool) |
93 | memcpy(engine->sram_pool, &sreq->op, sizeof(sreq->op)); |
94 | else |
95 | memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op)); |
96 | |
97 | len = mv_cesa_sg_copy_to_sram(engine, sgl: req->src, nents: creq->src_nents, |
98 | CESA_SA_DATA_SRAM_OFFSET, buflen: len, |
99 | skip: sreq->offset); |
100 | |
101 | sreq->size = len; |
102 | mv_cesa_set_crypt_op_len(op: &sreq->op, len); |
103 | |
104 | /* FIXME: only update enc_len field */ |
105 | if (!sreq->skip_ctx) { |
106 | if (engine->pool) |
107 | memcpy(engine->sram_pool, &sreq->op, sizeof(sreq->op)); |
108 | else |
109 | memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op)); |
110 | sreq->skip_ctx = true; |
111 | } else if (engine->pool) |
112 | memcpy(engine->sram_pool, &sreq->op, sizeof(sreq->op.desc)); |
113 | else |
114 | memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op.desc)); |
115 | |
116 | mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE); |
117 | writel_relaxed(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG); |
118 | WARN_ON(readl(engine->regs + CESA_SA_CMD) & |
119 | CESA_SA_CMD_EN_CESA_SA_ACCL0); |
120 | writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, addr: engine->regs + CESA_SA_CMD); |
121 | } |
122 | |
123 | static int mv_cesa_skcipher_std_process(struct skcipher_request *req, |
124 | u32 status) |
125 | { |
126 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
127 | struct mv_cesa_skcipher_std_req *sreq = &creq->std; |
128 | struct mv_cesa_engine *engine = creq->base.engine; |
129 | size_t len; |
130 | |
131 | len = mv_cesa_sg_copy_from_sram(engine, sgl: req->dst, nents: creq->dst_nents, |
132 | CESA_SA_DATA_SRAM_OFFSET, buflen: sreq->size, |
133 | skip: sreq->offset); |
134 | |
135 | sreq->offset += len; |
136 | if (sreq->offset < req->cryptlen) |
137 | return -EINPROGRESS; |
138 | |
139 | return 0; |
140 | } |
141 | |
142 | static int mv_cesa_skcipher_process(struct crypto_async_request *req, |
143 | u32 status) |
144 | { |
145 | struct skcipher_request *skreq = skcipher_request_cast(req); |
146 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req: skreq); |
147 | struct mv_cesa_req *basereq = &creq->base; |
148 | |
149 | if (mv_cesa_req_get_type(req: basereq) == CESA_STD_REQ) |
150 | return mv_cesa_skcipher_std_process(req: skreq, status); |
151 | |
152 | return mv_cesa_dma_process(dreq: basereq, status); |
153 | } |
154 | |
155 | static void mv_cesa_skcipher_step(struct crypto_async_request *req) |
156 | { |
157 | struct skcipher_request *skreq = skcipher_request_cast(req); |
158 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req: skreq); |
159 | |
160 | if (mv_cesa_req_get_type(req: &creq->base) == CESA_DMA_REQ) |
161 | mv_cesa_dma_step(dreq: &creq->base); |
162 | else |
163 | mv_cesa_skcipher_std_step(req: skreq); |
164 | } |
165 | |
166 | static inline void |
167 | mv_cesa_skcipher_dma_prepare(struct skcipher_request *req) |
168 | { |
169 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
170 | struct mv_cesa_req *basereq = &creq->base; |
171 | |
172 | mv_cesa_dma_prepare(dreq: basereq, engine: basereq->engine); |
173 | } |
174 | |
175 | static inline void |
176 | mv_cesa_skcipher_std_prepare(struct skcipher_request *req) |
177 | { |
178 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
179 | struct mv_cesa_skcipher_std_req *sreq = &creq->std; |
180 | |
181 | sreq->size = 0; |
182 | sreq->offset = 0; |
183 | } |
184 | |
185 | static inline void mv_cesa_skcipher_prepare(struct crypto_async_request *req, |
186 | struct mv_cesa_engine *engine) |
187 | { |
188 | struct skcipher_request *skreq = skcipher_request_cast(req); |
189 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req: skreq); |
190 | |
191 | creq->base.engine = engine; |
192 | |
193 | if (mv_cesa_req_get_type(req: &creq->base) == CESA_DMA_REQ) |
194 | mv_cesa_skcipher_dma_prepare(req: skreq); |
195 | else |
196 | mv_cesa_skcipher_std_prepare(req: skreq); |
197 | } |
198 | |
199 | static inline void |
200 | mv_cesa_skcipher_req_cleanup(struct crypto_async_request *req) |
201 | { |
202 | struct skcipher_request *skreq = skcipher_request_cast(req); |
203 | |
204 | mv_cesa_skcipher_cleanup(req: skreq); |
205 | } |
206 | |
207 | static void |
208 | mv_cesa_skcipher_complete(struct crypto_async_request *req) |
209 | { |
210 | struct skcipher_request *skreq = skcipher_request_cast(req); |
211 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req: skreq); |
212 | struct mv_cesa_engine *engine = creq->base.engine; |
213 | unsigned int ivsize; |
214 | |
215 | atomic_sub(i: skreq->cryptlen, v: &engine->load); |
216 | ivsize = crypto_skcipher_ivsize(tfm: crypto_skcipher_reqtfm(req: skreq)); |
217 | |
218 | if (mv_cesa_req_get_type(req: &creq->base) == CESA_DMA_REQ) { |
219 | struct mv_cesa_req *basereq; |
220 | |
221 | basereq = &creq->base; |
222 | memcpy(skreq->iv, basereq->chain.last->op->ctx.skcipher.iv, |
223 | ivsize); |
224 | } else if (engine->pool) |
225 | memcpy(skreq->iv, |
226 | engine->sram_pool + CESA_SA_CRYPT_IV_SRAM_OFFSET, |
227 | ivsize); |
228 | else |
229 | memcpy_fromio(skreq->iv, |
230 | engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET, |
231 | ivsize); |
232 | } |
233 | |
234 | static const struct mv_cesa_req_ops mv_cesa_skcipher_req_ops = { |
235 | .step = mv_cesa_skcipher_step, |
236 | .process = mv_cesa_skcipher_process, |
237 | .cleanup = mv_cesa_skcipher_req_cleanup, |
238 | .complete = mv_cesa_skcipher_complete, |
239 | }; |
240 | |
241 | static void mv_cesa_skcipher_cra_exit(struct crypto_tfm *tfm) |
242 | { |
243 | void *ctx = crypto_tfm_ctx(tfm); |
244 | |
245 | memzero_explicit(s: ctx, count: tfm->__crt_alg->cra_ctxsize); |
246 | } |
247 | |
248 | static int mv_cesa_skcipher_cra_init(struct crypto_tfm *tfm) |
249 | { |
250 | struct mv_cesa_ctx *ctx = crypto_tfm_ctx(tfm); |
251 | |
252 | ctx->ops = &mv_cesa_skcipher_req_ops; |
253 | |
254 | crypto_skcipher_set_reqsize(skcipher: __crypto_skcipher_cast(tfm), |
255 | reqsize: sizeof(struct mv_cesa_skcipher_req)); |
256 | |
257 | return 0; |
258 | } |
259 | |
260 | static int mv_cesa_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, |
261 | unsigned int len) |
262 | { |
263 | struct crypto_tfm *tfm = crypto_skcipher_tfm(tfm: cipher); |
264 | struct mv_cesa_aes_ctx *ctx = crypto_tfm_ctx(tfm); |
265 | int remaining; |
266 | int offset; |
267 | int ret; |
268 | int i; |
269 | |
270 | ret = aes_expandkey(ctx: &ctx->aes, in_key: key, key_len: len); |
271 | if (ret) |
272 | return ret; |
273 | |
274 | remaining = (ctx->aes.key_length - 16) / 4; |
275 | offset = ctx->aes.key_length + 24 - remaining; |
276 | for (i = 0; i < remaining; i++) |
277 | ctx->aes.key_dec[4 + i] = ctx->aes.key_enc[offset + i]; |
278 | |
279 | return 0; |
280 | } |
281 | |
282 | static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key, |
283 | unsigned int len) |
284 | { |
285 | struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(tfm: cipher); |
286 | int err; |
287 | |
288 | err = verify_skcipher_des_key(tfm: cipher, key); |
289 | if (err) |
290 | return err; |
291 | |
292 | memcpy(ctx->key, key, DES_KEY_SIZE); |
293 | |
294 | return 0; |
295 | } |
296 | |
297 | static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher, |
298 | const u8 *key, unsigned int len) |
299 | { |
300 | struct mv_cesa_des3_ctx *ctx = crypto_skcipher_ctx(tfm: cipher); |
301 | int err; |
302 | |
303 | err = verify_skcipher_des3_key(tfm: cipher, key); |
304 | if (err) |
305 | return err; |
306 | |
307 | memcpy(ctx->key, key, DES3_EDE_KEY_SIZE); |
308 | |
309 | return 0; |
310 | } |
311 | |
312 | static int mv_cesa_skcipher_dma_req_init(struct skcipher_request *req, |
313 | const struct mv_cesa_op_ctx *op_templ) |
314 | { |
315 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
316 | gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? |
317 | GFP_KERNEL : GFP_ATOMIC; |
318 | struct mv_cesa_req *basereq = &creq->base; |
319 | struct mv_cesa_skcipher_dma_iter iter; |
320 | bool skip_ctx = false; |
321 | int ret; |
322 | |
323 | basereq->chain.first = NULL; |
324 | basereq->chain.last = NULL; |
325 | |
326 | if (req->src != req->dst) { |
327 | ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents, |
328 | DMA_TO_DEVICE); |
329 | if (!ret) |
330 | return -ENOMEM; |
331 | |
332 | ret = dma_map_sg(cesa_dev->dev, req->dst, creq->dst_nents, |
333 | DMA_FROM_DEVICE); |
334 | if (!ret) { |
335 | ret = -ENOMEM; |
336 | goto err_unmap_src; |
337 | } |
338 | } else { |
339 | ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents, |
340 | DMA_BIDIRECTIONAL); |
341 | if (!ret) |
342 | return -ENOMEM; |
343 | } |
344 | |
345 | mv_cesa_tdma_desc_iter_init(chain: &basereq->chain); |
346 | mv_cesa_skcipher_req_iter_init(iter: &iter, req); |
347 | |
348 | do { |
349 | struct mv_cesa_op_ctx *op; |
350 | |
351 | op = mv_cesa_dma_add_op(chain: &basereq->chain, op_templ, skip_ctx, |
352 | flags); |
353 | if (IS_ERR(ptr: op)) { |
354 | ret = PTR_ERR(ptr: op); |
355 | goto err_free_tdma; |
356 | } |
357 | skip_ctx = true; |
358 | |
359 | mv_cesa_set_crypt_op_len(op, len: iter.base.op_len); |
360 | |
361 | /* Add input transfers */ |
362 | ret = mv_cesa_dma_add_op_transfers(chain: &basereq->chain, dma_iter: &iter.base, |
363 | sgiter: &iter.src, gfp_flags: flags); |
364 | if (ret) |
365 | goto err_free_tdma; |
366 | |
367 | /* Add dummy desc to launch the crypto operation */ |
368 | ret = mv_cesa_dma_add_dummy_launch(chain: &basereq->chain, flags); |
369 | if (ret) |
370 | goto err_free_tdma; |
371 | |
372 | /* Add output transfers */ |
373 | ret = mv_cesa_dma_add_op_transfers(chain: &basereq->chain, dma_iter: &iter.base, |
374 | sgiter: &iter.dst, gfp_flags: flags); |
375 | if (ret) |
376 | goto err_free_tdma; |
377 | |
378 | } while (mv_cesa_skcipher_req_iter_next_op(iter: &iter)); |
379 | |
380 | /* Add output data for IV */ |
381 | ret = mv_cesa_dma_add_result_op(chain: &basereq->chain, |
382 | CESA_SA_CFG_SRAM_OFFSET, |
383 | CESA_SA_DATA_SRAM_OFFSET, |
384 | CESA_TDMA_SRC_IN_SRAM, gfp_flags: flags); |
385 | |
386 | if (ret) |
387 | goto err_free_tdma; |
388 | |
389 | basereq->chain.last->flags |= CESA_TDMA_END_OF_REQ; |
390 | |
391 | return 0; |
392 | |
393 | err_free_tdma: |
394 | mv_cesa_dma_cleanup(dreq: basereq); |
395 | if (req->dst != req->src) |
396 | dma_unmap_sg(cesa_dev->dev, req->dst, creq->dst_nents, |
397 | DMA_FROM_DEVICE); |
398 | |
399 | err_unmap_src: |
400 | dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, |
401 | req->dst != req->src ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL); |
402 | |
403 | return ret; |
404 | } |
405 | |
406 | static inline int |
407 | mv_cesa_skcipher_std_req_init(struct skcipher_request *req, |
408 | const struct mv_cesa_op_ctx *op_templ) |
409 | { |
410 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
411 | struct mv_cesa_skcipher_std_req *sreq = &creq->std; |
412 | struct mv_cesa_req *basereq = &creq->base; |
413 | |
414 | sreq->op = *op_templ; |
415 | sreq->skip_ctx = false; |
416 | basereq->chain.first = NULL; |
417 | basereq->chain.last = NULL; |
418 | |
419 | return 0; |
420 | } |
421 | |
422 | static int mv_cesa_skcipher_req_init(struct skcipher_request *req, |
423 | struct mv_cesa_op_ctx *tmpl) |
424 | { |
425 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
426 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
427 | unsigned int blksize = crypto_skcipher_blocksize(tfm); |
428 | int ret; |
429 | |
430 | if (!IS_ALIGNED(req->cryptlen, blksize)) |
431 | return -EINVAL; |
432 | |
433 | creq->src_nents = sg_nents_for_len(sg: req->src, len: req->cryptlen); |
434 | if (creq->src_nents < 0) { |
435 | dev_err(cesa_dev->dev, "Invalid number of src SG" ); |
436 | return creq->src_nents; |
437 | } |
438 | creq->dst_nents = sg_nents_for_len(sg: req->dst, len: req->cryptlen); |
439 | if (creq->dst_nents < 0) { |
440 | dev_err(cesa_dev->dev, "Invalid number of dst SG" ); |
441 | return creq->dst_nents; |
442 | } |
443 | |
444 | mv_cesa_update_op_cfg(op: tmpl, CESA_SA_DESC_CFG_OP_CRYPT_ONLY, |
445 | CESA_SA_DESC_CFG_OP_MSK); |
446 | |
447 | if (cesa_dev->caps->has_tdma) |
448 | ret = mv_cesa_skcipher_dma_req_init(req, op_templ: tmpl); |
449 | else |
450 | ret = mv_cesa_skcipher_std_req_init(req, op_templ: tmpl); |
451 | |
452 | return ret; |
453 | } |
454 | |
455 | static int mv_cesa_skcipher_queue_req(struct skcipher_request *req, |
456 | struct mv_cesa_op_ctx *tmpl) |
457 | { |
458 | int ret; |
459 | struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); |
460 | struct mv_cesa_engine *engine; |
461 | |
462 | ret = mv_cesa_skcipher_req_init(req, tmpl); |
463 | if (ret) |
464 | return ret; |
465 | |
466 | engine = mv_cesa_select_engine(weight: req->cryptlen); |
467 | mv_cesa_skcipher_prepare(req: &req->base, engine); |
468 | |
469 | ret = mv_cesa_queue_req(req: &req->base, creq: &creq->base); |
470 | |
471 | if (mv_cesa_req_needs_cleanup(req: &req->base, ret)) |
472 | mv_cesa_skcipher_cleanup(req); |
473 | |
474 | return ret; |
475 | } |
476 | |
477 | static int mv_cesa_des_op(struct skcipher_request *req, |
478 | struct mv_cesa_op_ctx *tmpl) |
479 | { |
480 | struct mv_cesa_des_ctx *ctx = crypto_tfm_ctx(tfm: req->base.tfm); |
481 | |
482 | mv_cesa_update_op_cfg(op: tmpl, CESA_SA_DESC_CFG_CRYPTM_DES, |
483 | CESA_SA_DESC_CFG_CRYPTM_MSK); |
484 | |
485 | memcpy(tmpl->ctx.skcipher.key, ctx->key, DES_KEY_SIZE); |
486 | |
487 | return mv_cesa_skcipher_queue_req(req, tmpl); |
488 | } |
489 | |
490 | static int mv_cesa_ecb_des_encrypt(struct skcipher_request *req) |
491 | { |
492 | struct mv_cesa_op_ctx tmpl; |
493 | |
494 | mv_cesa_set_op_cfg(op: &tmpl, |
495 | CESA_SA_DESC_CFG_CRYPTCM_ECB | |
496 | CESA_SA_DESC_CFG_DIR_ENC); |
497 | |
498 | return mv_cesa_des_op(req, tmpl: &tmpl); |
499 | } |
500 | |
501 | static int mv_cesa_ecb_des_decrypt(struct skcipher_request *req) |
502 | { |
503 | struct mv_cesa_op_ctx tmpl; |
504 | |
505 | mv_cesa_set_op_cfg(op: &tmpl, |
506 | CESA_SA_DESC_CFG_CRYPTCM_ECB | |
507 | CESA_SA_DESC_CFG_DIR_DEC); |
508 | |
509 | return mv_cesa_des_op(req, tmpl: &tmpl); |
510 | } |
511 | |
512 | struct skcipher_alg mv_cesa_ecb_des_alg = { |
513 | .setkey = mv_cesa_des_setkey, |
514 | .encrypt = mv_cesa_ecb_des_encrypt, |
515 | .decrypt = mv_cesa_ecb_des_decrypt, |
516 | .min_keysize = DES_KEY_SIZE, |
517 | .max_keysize = DES_KEY_SIZE, |
518 | .base = { |
519 | .cra_name = "ecb(des)" , |
520 | .cra_driver_name = "mv-ecb-des" , |
521 | .cra_priority = 300, |
522 | .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | |
523 | CRYPTO_ALG_ALLOCATES_MEMORY, |
524 | .cra_blocksize = DES_BLOCK_SIZE, |
525 | .cra_ctxsize = sizeof(struct mv_cesa_des_ctx), |
526 | .cra_alignmask = 0, |
527 | .cra_module = THIS_MODULE, |
528 | .cra_init = mv_cesa_skcipher_cra_init, |
529 | .cra_exit = mv_cesa_skcipher_cra_exit, |
530 | }, |
531 | }; |
532 | |
533 | static int mv_cesa_cbc_des_op(struct skcipher_request *req, |
534 | struct mv_cesa_op_ctx *tmpl) |
535 | { |
536 | mv_cesa_update_op_cfg(op: tmpl, CESA_SA_DESC_CFG_CRYPTCM_CBC, |
537 | CESA_SA_DESC_CFG_CRYPTCM_MSK); |
538 | |
539 | memcpy(tmpl->ctx.skcipher.iv, req->iv, DES_BLOCK_SIZE); |
540 | |
541 | return mv_cesa_des_op(req, tmpl); |
542 | } |
543 | |
544 | static int mv_cesa_cbc_des_encrypt(struct skcipher_request *req) |
545 | { |
546 | struct mv_cesa_op_ctx tmpl; |
547 | |
548 | mv_cesa_set_op_cfg(op: &tmpl, CESA_SA_DESC_CFG_DIR_ENC); |
549 | |
550 | return mv_cesa_cbc_des_op(req, tmpl: &tmpl); |
551 | } |
552 | |
553 | static int mv_cesa_cbc_des_decrypt(struct skcipher_request *req) |
554 | { |
555 | struct mv_cesa_op_ctx tmpl; |
556 | |
557 | mv_cesa_set_op_cfg(op: &tmpl, CESA_SA_DESC_CFG_DIR_DEC); |
558 | |
559 | return mv_cesa_cbc_des_op(req, tmpl: &tmpl); |
560 | } |
561 | |
562 | struct skcipher_alg mv_cesa_cbc_des_alg = { |
563 | .setkey = mv_cesa_des_setkey, |
564 | .encrypt = mv_cesa_cbc_des_encrypt, |
565 | .decrypt = mv_cesa_cbc_des_decrypt, |
566 | .min_keysize = DES_KEY_SIZE, |
567 | .max_keysize = DES_KEY_SIZE, |
568 | .ivsize = DES_BLOCK_SIZE, |
569 | .base = { |
570 | .cra_name = "cbc(des)" , |
571 | .cra_driver_name = "mv-cbc-des" , |
572 | .cra_priority = 300, |
573 | .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | |
574 | CRYPTO_ALG_ALLOCATES_MEMORY, |
575 | .cra_blocksize = DES_BLOCK_SIZE, |
576 | .cra_ctxsize = sizeof(struct mv_cesa_des_ctx), |
577 | .cra_alignmask = 0, |
578 | .cra_module = THIS_MODULE, |
579 | .cra_init = mv_cesa_skcipher_cra_init, |
580 | .cra_exit = mv_cesa_skcipher_cra_exit, |
581 | }, |
582 | }; |
583 | |
584 | static int mv_cesa_des3_op(struct skcipher_request *req, |
585 | struct mv_cesa_op_ctx *tmpl) |
586 | { |
587 | struct mv_cesa_des3_ctx *ctx = crypto_tfm_ctx(tfm: req->base.tfm); |
588 | |
589 | mv_cesa_update_op_cfg(op: tmpl, CESA_SA_DESC_CFG_CRYPTM_3DES, |
590 | CESA_SA_DESC_CFG_CRYPTM_MSK); |
591 | |
592 | memcpy(tmpl->ctx.skcipher.key, ctx->key, DES3_EDE_KEY_SIZE); |
593 | |
594 | return mv_cesa_skcipher_queue_req(req, tmpl); |
595 | } |
596 | |
597 | static int mv_cesa_ecb_des3_ede_encrypt(struct skcipher_request *req) |
598 | { |
599 | struct mv_cesa_op_ctx tmpl; |
600 | |
601 | mv_cesa_set_op_cfg(op: &tmpl, |
602 | CESA_SA_DESC_CFG_CRYPTCM_ECB | |
603 | CESA_SA_DESC_CFG_3DES_EDE | |
604 | CESA_SA_DESC_CFG_DIR_ENC); |
605 | |
606 | return mv_cesa_des3_op(req, tmpl: &tmpl); |
607 | } |
608 | |
609 | static int mv_cesa_ecb_des3_ede_decrypt(struct skcipher_request *req) |
610 | { |
611 | struct mv_cesa_op_ctx tmpl; |
612 | |
613 | mv_cesa_set_op_cfg(op: &tmpl, |
614 | CESA_SA_DESC_CFG_CRYPTCM_ECB | |
615 | CESA_SA_DESC_CFG_3DES_EDE | |
616 | CESA_SA_DESC_CFG_DIR_DEC); |
617 | |
618 | return mv_cesa_des3_op(req, tmpl: &tmpl); |
619 | } |
620 | |
621 | struct skcipher_alg mv_cesa_ecb_des3_ede_alg = { |
622 | .setkey = mv_cesa_des3_ede_setkey, |
623 | .encrypt = mv_cesa_ecb_des3_ede_encrypt, |
624 | .decrypt = mv_cesa_ecb_des3_ede_decrypt, |
625 | .min_keysize = DES3_EDE_KEY_SIZE, |
626 | .max_keysize = DES3_EDE_KEY_SIZE, |
627 | .base = { |
628 | .cra_name = "ecb(des3_ede)" , |
629 | .cra_driver_name = "mv-ecb-des3-ede" , |
630 | .cra_priority = 300, |
631 | .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | |
632 | CRYPTO_ALG_ALLOCATES_MEMORY, |
633 | .cra_blocksize = DES3_EDE_BLOCK_SIZE, |
634 | .cra_ctxsize = sizeof(struct mv_cesa_des3_ctx), |
635 | .cra_alignmask = 0, |
636 | .cra_module = THIS_MODULE, |
637 | .cra_init = mv_cesa_skcipher_cra_init, |
638 | .cra_exit = mv_cesa_skcipher_cra_exit, |
639 | }, |
640 | }; |
641 | |
642 | static int mv_cesa_cbc_des3_op(struct skcipher_request *req, |
643 | struct mv_cesa_op_ctx *tmpl) |
644 | { |
645 | memcpy(tmpl->ctx.skcipher.iv, req->iv, DES3_EDE_BLOCK_SIZE); |
646 | |
647 | return mv_cesa_des3_op(req, tmpl); |
648 | } |
649 | |
650 | static int mv_cesa_cbc_des3_ede_encrypt(struct skcipher_request *req) |
651 | { |
652 | struct mv_cesa_op_ctx tmpl; |
653 | |
654 | mv_cesa_set_op_cfg(op: &tmpl, |
655 | CESA_SA_DESC_CFG_CRYPTCM_CBC | |
656 | CESA_SA_DESC_CFG_3DES_EDE | |
657 | CESA_SA_DESC_CFG_DIR_ENC); |
658 | |
659 | return mv_cesa_cbc_des3_op(req, tmpl: &tmpl); |
660 | } |
661 | |
662 | static int mv_cesa_cbc_des3_ede_decrypt(struct skcipher_request *req) |
663 | { |
664 | struct mv_cesa_op_ctx tmpl; |
665 | |
666 | mv_cesa_set_op_cfg(op: &tmpl, |
667 | CESA_SA_DESC_CFG_CRYPTCM_CBC | |
668 | CESA_SA_DESC_CFG_3DES_EDE | |
669 | CESA_SA_DESC_CFG_DIR_DEC); |
670 | |
671 | return mv_cesa_cbc_des3_op(req, tmpl: &tmpl); |
672 | } |
673 | |
674 | struct skcipher_alg mv_cesa_cbc_des3_ede_alg = { |
675 | .setkey = mv_cesa_des3_ede_setkey, |
676 | .encrypt = mv_cesa_cbc_des3_ede_encrypt, |
677 | .decrypt = mv_cesa_cbc_des3_ede_decrypt, |
678 | .min_keysize = DES3_EDE_KEY_SIZE, |
679 | .max_keysize = DES3_EDE_KEY_SIZE, |
680 | .ivsize = DES3_EDE_BLOCK_SIZE, |
681 | .base = { |
682 | .cra_name = "cbc(des3_ede)" , |
683 | .cra_driver_name = "mv-cbc-des3-ede" , |
684 | .cra_priority = 300, |
685 | .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | |
686 | CRYPTO_ALG_ALLOCATES_MEMORY, |
687 | .cra_blocksize = DES3_EDE_BLOCK_SIZE, |
688 | .cra_ctxsize = sizeof(struct mv_cesa_des3_ctx), |
689 | .cra_alignmask = 0, |
690 | .cra_module = THIS_MODULE, |
691 | .cra_init = mv_cesa_skcipher_cra_init, |
692 | .cra_exit = mv_cesa_skcipher_cra_exit, |
693 | }, |
694 | }; |
695 | |
696 | static int mv_cesa_aes_op(struct skcipher_request *req, |
697 | struct mv_cesa_op_ctx *tmpl) |
698 | { |
699 | struct mv_cesa_aes_ctx *ctx = crypto_tfm_ctx(tfm: req->base.tfm); |
700 | int i; |
701 | u32 *key; |
702 | u32 cfg; |
703 | |
704 | cfg = CESA_SA_DESC_CFG_CRYPTM_AES; |
705 | |
706 | if (mv_cesa_get_op_cfg(op: tmpl) & CESA_SA_DESC_CFG_DIR_DEC) |
707 | key = ctx->aes.key_dec; |
708 | else |
709 | key = ctx->aes.key_enc; |
710 | |
711 | for (i = 0; i < ctx->aes.key_length / sizeof(u32); i++) |
712 | tmpl->ctx.skcipher.key[i] = cpu_to_le32(key[i]); |
713 | |
714 | if (ctx->aes.key_length == 24) |
715 | cfg |= CESA_SA_DESC_CFG_AES_LEN_192; |
716 | else if (ctx->aes.key_length == 32) |
717 | cfg |= CESA_SA_DESC_CFG_AES_LEN_256; |
718 | |
719 | mv_cesa_update_op_cfg(op: tmpl, cfg, |
720 | CESA_SA_DESC_CFG_CRYPTM_MSK | |
721 | CESA_SA_DESC_CFG_AES_LEN_MSK); |
722 | |
723 | return mv_cesa_skcipher_queue_req(req, tmpl); |
724 | } |
725 | |
726 | static int mv_cesa_ecb_aes_encrypt(struct skcipher_request *req) |
727 | { |
728 | struct mv_cesa_op_ctx tmpl; |
729 | |
730 | mv_cesa_set_op_cfg(op: &tmpl, |
731 | CESA_SA_DESC_CFG_CRYPTCM_ECB | |
732 | CESA_SA_DESC_CFG_DIR_ENC); |
733 | |
734 | return mv_cesa_aes_op(req, tmpl: &tmpl); |
735 | } |
736 | |
737 | static int mv_cesa_ecb_aes_decrypt(struct skcipher_request *req) |
738 | { |
739 | struct mv_cesa_op_ctx tmpl; |
740 | |
741 | mv_cesa_set_op_cfg(op: &tmpl, |
742 | CESA_SA_DESC_CFG_CRYPTCM_ECB | |
743 | CESA_SA_DESC_CFG_DIR_DEC); |
744 | |
745 | return mv_cesa_aes_op(req, tmpl: &tmpl); |
746 | } |
747 | |
748 | struct skcipher_alg mv_cesa_ecb_aes_alg = { |
749 | .setkey = mv_cesa_aes_setkey, |
750 | .encrypt = mv_cesa_ecb_aes_encrypt, |
751 | .decrypt = mv_cesa_ecb_aes_decrypt, |
752 | .min_keysize = AES_MIN_KEY_SIZE, |
753 | .max_keysize = AES_MAX_KEY_SIZE, |
754 | .base = { |
755 | .cra_name = "ecb(aes)" , |
756 | .cra_driver_name = "mv-ecb-aes" , |
757 | .cra_priority = 300, |
758 | .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | |
759 | CRYPTO_ALG_ALLOCATES_MEMORY, |
760 | .cra_blocksize = AES_BLOCK_SIZE, |
761 | .cra_ctxsize = sizeof(struct mv_cesa_aes_ctx), |
762 | .cra_alignmask = 0, |
763 | .cra_module = THIS_MODULE, |
764 | .cra_init = mv_cesa_skcipher_cra_init, |
765 | .cra_exit = mv_cesa_skcipher_cra_exit, |
766 | }, |
767 | }; |
768 | |
769 | static int mv_cesa_cbc_aes_op(struct skcipher_request *req, |
770 | struct mv_cesa_op_ctx *tmpl) |
771 | { |
772 | mv_cesa_update_op_cfg(op: tmpl, CESA_SA_DESC_CFG_CRYPTCM_CBC, |
773 | CESA_SA_DESC_CFG_CRYPTCM_MSK); |
774 | memcpy(tmpl->ctx.skcipher.iv, req->iv, AES_BLOCK_SIZE); |
775 | |
776 | return mv_cesa_aes_op(req, tmpl); |
777 | } |
778 | |
779 | static int mv_cesa_cbc_aes_encrypt(struct skcipher_request *req) |
780 | { |
781 | struct mv_cesa_op_ctx tmpl; |
782 | |
783 | mv_cesa_set_op_cfg(op: &tmpl, CESA_SA_DESC_CFG_DIR_ENC); |
784 | |
785 | return mv_cesa_cbc_aes_op(req, tmpl: &tmpl); |
786 | } |
787 | |
788 | static int mv_cesa_cbc_aes_decrypt(struct skcipher_request *req) |
789 | { |
790 | struct mv_cesa_op_ctx tmpl; |
791 | |
792 | mv_cesa_set_op_cfg(op: &tmpl, CESA_SA_DESC_CFG_DIR_DEC); |
793 | |
794 | return mv_cesa_cbc_aes_op(req, tmpl: &tmpl); |
795 | } |
796 | |
797 | struct skcipher_alg mv_cesa_cbc_aes_alg = { |
798 | .setkey = mv_cesa_aes_setkey, |
799 | .encrypt = mv_cesa_cbc_aes_encrypt, |
800 | .decrypt = mv_cesa_cbc_aes_decrypt, |
801 | .min_keysize = AES_MIN_KEY_SIZE, |
802 | .max_keysize = AES_MAX_KEY_SIZE, |
803 | .ivsize = AES_BLOCK_SIZE, |
804 | .base = { |
805 | .cra_name = "cbc(aes)" , |
806 | .cra_driver_name = "mv-cbc-aes" , |
807 | .cra_priority = 300, |
808 | .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | |
809 | CRYPTO_ALG_ALLOCATES_MEMORY, |
810 | .cra_blocksize = AES_BLOCK_SIZE, |
811 | .cra_ctxsize = sizeof(struct mv_cesa_aes_ctx), |
812 | .cra_alignmask = 0, |
813 | .cra_module = THIS_MODULE, |
814 | .cra_init = mv_cesa_skcipher_cra_init, |
815 | .cra_exit = mv_cesa_skcipher_cra_exit, |
816 | }, |
817 | }; |
818 | |