]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/crypto/marvell/hash.c
crypto: marvell/cesa - fix the bit length endianness
[mirror_ubuntu-hirsute-kernel.git] / drivers / crypto / marvell / hash.c
CommitLineData
f63601fd
BB
1/*
2 * Hash algorithms supported by the CESA: MD5, SHA1 and SHA256.
3 *
4 * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
5 * Author: Arnaud Ebalard <arno@natisbad.org>
6 *
7 * This work is based on an initial version written by
8 * Sebastian Andrzej Siewior < sebastian at breakpoint dot cc >
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
7aeef693 15#include <crypto/md5.h>
f63601fd
BB
16#include <crypto/sha.h>
17
18#include "cesa.h"
19
db509a45
BB
20struct mv_cesa_ahash_dma_iter {
21 struct mv_cesa_dma_iter base;
22 struct mv_cesa_sg_dma_iter src;
23};
24
25static inline void
26mv_cesa_ahash_req_iter_init(struct mv_cesa_ahash_dma_iter *iter,
27 struct ahash_request *req)
28{
29 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
30 unsigned int len = req->nbytes;
31
32 if (!creq->last_req)
33 len = (len + creq->cache_ptr) & ~CESA_HASH_BLOCK_SIZE_MSK;
34
35 mv_cesa_req_dma_iter_init(&iter->base, len);
36 mv_cesa_sg_dma_iter_init(&iter->src, req->src, DMA_TO_DEVICE);
37 iter->src.op_offset = creq->cache_ptr;
38}
39
40static inline bool
41mv_cesa_ahash_req_iter_next_op(struct mv_cesa_ahash_dma_iter *iter)
42{
43 iter->src.op_offset = 0;
44
45 return mv_cesa_req_dma_iter_next_op(&iter->base);
46}
47
48static inline int mv_cesa_ahash_dma_alloc_cache(struct mv_cesa_ahash_req *creq,
49 gfp_t flags)
50{
51 struct mv_cesa_ahash_dma_req *dreq = &creq->req.dma;
52
53 creq->cache = dma_pool_alloc(cesa_dev->dma->cache_pool, flags,
54 &dreq->cache_dma);
55 if (!creq->cache)
56 return -ENOMEM;
57
58 return 0;
59}
60
f63601fd
BB
61static inline int mv_cesa_ahash_std_alloc_cache(struct mv_cesa_ahash_req *creq,
62 gfp_t flags)
63{
64 creq->cache = kzalloc(CESA_MAX_HASH_BLOCK_SIZE, flags);
65 if (!creq->cache)
66 return -ENOMEM;
67
68 return 0;
69}
70
71static int mv_cesa_ahash_alloc_cache(struct ahash_request *req)
72{
73 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
74 gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
75 GFP_KERNEL : GFP_ATOMIC;
db509a45 76 int ret;
f63601fd
BB
77
78 if (creq->cache)
79 return 0;
80
db509a45
BB
81 if (creq->req.base.type == CESA_DMA_REQ)
82 ret = mv_cesa_ahash_dma_alloc_cache(creq, flags);
83 else
84 ret = mv_cesa_ahash_std_alloc_cache(creq, flags);
85
86 return ret;
87}
88
89static inline void mv_cesa_ahash_dma_free_cache(struct mv_cesa_ahash_req *creq)
90{
91 dma_pool_free(cesa_dev->dma->cache_pool, creq->cache,
92 creq->req.dma.cache_dma);
f63601fd
BB
93}
94
95static inline void mv_cesa_ahash_std_free_cache(struct mv_cesa_ahash_req *creq)
96{
97 kfree(creq->cache);
98}
99
100static void mv_cesa_ahash_free_cache(struct mv_cesa_ahash_req *creq)
101{
102 if (!creq->cache)
103 return;
104
db509a45
BB
105 if (creq->req.base.type == CESA_DMA_REQ)
106 mv_cesa_ahash_dma_free_cache(creq);
107 else
108 mv_cesa_ahash_std_free_cache(creq);
f63601fd
BB
109
110 creq->cache = NULL;
111}
112
db509a45
BB
113static int mv_cesa_ahash_dma_alloc_padding(struct mv_cesa_ahash_dma_req *req,
114 gfp_t flags)
115{
116 if (req->padding)
117 return 0;
118
119 req->padding = dma_pool_alloc(cesa_dev->dma->padding_pool, flags,
120 &req->padding_dma);
121 if (!req->padding)
122 return -ENOMEM;
123
124 return 0;
125}
126
127static void mv_cesa_ahash_dma_free_padding(struct mv_cesa_ahash_dma_req *req)
128{
129 if (!req->padding)
130 return;
131
132 dma_pool_free(cesa_dev->dma->padding_pool, req->padding,
133 req->padding_dma);
134 req->padding = NULL;
135}
136
137static inline void mv_cesa_ahash_dma_last_cleanup(struct ahash_request *req)
138{
139 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
140
141 mv_cesa_ahash_dma_free_padding(&creq->req.dma);
142}
143
144static inline void mv_cesa_ahash_dma_cleanup(struct ahash_request *req)
145{
146 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
147
148 dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE);
149 mv_cesa_dma_cleanup(&creq->req.dma.base);
150}
151
152static inline void mv_cesa_ahash_cleanup(struct ahash_request *req)
153{
154 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
155
156 if (creq->req.base.type == CESA_DMA_REQ)
157 mv_cesa_ahash_dma_cleanup(req);
158}
159
f63601fd
BB
160static void mv_cesa_ahash_last_cleanup(struct ahash_request *req)
161{
162 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
163
164 mv_cesa_ahash_free_cache(creq);
db509a45
BB
165
166 if (creq->req.base.type == CESA_DMA_REQ)
167 mv_cesa_ahash_dma_last_cleanup(req);
f63601fd
BB
168}
169
170static int mv_cesa_ahash_pad_len(struct mv_cesa_ahash_req *creq)
171{
172 unsigned int index, padlen;
173
174 index = creq->len & CESA_HASH_BLOCK_SIZE_MSK;
175 padlen = (index < 56) ? (56 - index) : (64 + 56 - index);
176
177 return padlen;
178}
179
180static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf)
181{
f63601fd
BB
182 unsigned int index, padlen;
183
184 buf[0] = 0x80;
185 /* Pad out to 56 mod 64 */
186 index = creq->len & CESA_HASH_BLOCK_SIZE_MSK;
187 padlen = mv_cesa_ahash_pad_len(creq);
188 memset(buf + 1, 0, padlen - 1);
51954a96
RK
189
190 if (creq->algo_le) {
191 __le64 bits = cpu_to_le64(creq->len << 3);
192 memcpy(buf + padlen, &bits, sizeof(bits));
193 } else {
194 __be64 bits = cpu_to_be64(creq->len << 3);
195 memcpy(buf + padlen, &bits, sizeof(bits));
196 }
f63601fd
BB
197
198 return padlen + 8;
199}
200
201static void mv_cesa_ahash_std_step(struct ahash_request *req)
202{
203 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
204 struct mv_cesa_ahash_std_req *sreq = &creq->req.std;
205 struct mv_cesa_engine *engine = sreq->base.engine;
206 struct mv_cesa_op_ctx *op;
207 unsigned int new_cache_ptr = 0;
208 u32 frag_mode;
209 size_t len;
210
211 if (creq->cache_ptr)
212 memcpy(engine->sram + CESA_SA_DATA_SRAM_OFFSET, creq->cache,
213 creq->cache_ptr);
214
215 len = min_t(size_t, req->nbytes + creq->cache_ptr - sreq->offset,
216 CESA_SA_SRAM_PAYLOAD_SIZE);
217
218 if (!creq->last_req) {
219 new_cache_ptr = len & CESA_HASH_BLOCK_SIZE_MSK;
220 len &= ~CESA_HASH_BLOCK_SIZE_MSK;
221 }
222
223 if (len - creq->cache_ptr)
224 sreq->offset += sg_pcopy_to_buffer(req->src, creq->src_nents,
225 engine->sram +
226 CESA_SA_DATA_SRAM_OFFSET +
227 creq->cache_ptr,
228 len - creq->cache_ptr,
229 sreq->offset);
230
231 op = &creq->op_tmpl;
232
233 frag_mode = mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK;
234
235 if (creq->last_req && sreq->offset == req->nbytes &&
236 creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
237 if (frag_mode == CESA_SA_DESC_CFG_FIRST_FRAG)
238 frag_mode = CESA_SA_DESC_CFG_NOT_FRAG;
239 else if (frag_mode == CESA_SA_DESC_CFG_MID_FRAG)
240 frag_mode = CESA_SA_DESC_CFG_LAST_FRAG;
241 }
242
243 if (frag_mode == CESA_SA_DESC_CFG_NOT_FRAG ||
244 frag_mode == CESA_SA_DESC_CFG_LAST_FRAG) {
245 if (len &&
246 creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
247 mv_cesa_set_mac_op_total_len(op, creq->len);
248 } else {
249 int trailerlen = mv_cesa_ahash_pad_len(creq) + 8;
250
251 if (len + trailerlen > CESA_SA_SRAM_PAYLOAD_SIZE) {
252 len &= CESA_HASH_BLOCK_SIZE_MSK;
253 new_cache_ptr = 64 - trailerlen;
254 memcpy(creq->cache,
255 engine->sram +
256 CESA_SA_DATA_SRAM_OFFSET + len,
257 new_cache_ptr);
258 } else {
259 len += mv_cesa_ahash_pad_req(creq,
260 engine->sram + len +
261 CESA_SA_DATA_SRAM_OFFSET);
262 }
263
264 if (frag_mode == CESA_SA_DESC_CFG_LAST_FRAG)
265 frag_mode = CESA_SA_DESC_CFG_MID_FRAG;
266 else
267 frag_mode = CESA_SA_DESC_CFG_FIRST_FRAG;
268 }
269 }
270
271 mv_cesa_set_mac_op_frag_len(op, len);
272 mv_cesa_update_op_cfg(op, frag_mode, CESA_SA_DESC_CFG_FRAG_MSK);
273
274 /* FIXME: only update enc_len field */
275 memcpy(engine->sram, op, sizeof(*op));
276
277 if (frag_mode == CESA_SA_DESC_CFG_FIRST_FRAG)
278 mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
279 CESA_SA_DESC_CFG_FRAG_MSK);
280
281 creq->cache_ptr = new_cache_ptr;
282
283 mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE);
284 writel(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
285 writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
286}
287
288static int mv_cesa_ahash_std_process(struct ahash_request *req, u32 status)
289{
290 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
291 struct mv_cesa_ahash_std_req *sreq = &creq->req.std;
292
293 if (sreq->offset < (req->nbytes - creq->cache_ptr))
294 return -EINPROGRESS;
295
296 return 0;
297}
298
db509a45
BB
299static inline void mv_cesa_ahash_dma_prepare(struct ahash_request *req)
300{
301 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
302 struct mv_cesa_tdma_req *dreq = &creq->req.dma.base;
303
304 mv_cesa_dma_prepare(dreq, dreq->base.engine);
305}
306
f63601fd
BB
307static void mv_cesa_ahash_std_prepare(struct ahash_request *req)
308{
309 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
310 struct mv_cesa_ahash_std_req *sreq = &creq->req.std;
311 struct mv_cesa_engine *engine = sreq->base.engine;
312
313 sreq->offset = 0;
314 mv_cesa_adjust_op(engine, &creq->op_tmpl);
315 memcpy(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
316}
317
318static void mv_cesa_ahash_step(struct crypto_async_request *req)
319{
320 struct ahash_request *ahashreq = ahash_request_cast(req);
db509a45 321 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
f63601fd 322
db509a45
BB
323 if (creq->req.base.type == CESA_DMA_REQ)
324 mv_cesa_dma_step(&creq->req.dma.base);
325 else
326 mv_cesa_ahash_std_step(ahashreq);
f63601fd
BB
327}
328
329static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status)
330{
331 struct ahash_request *ahashreq = ahash_request_cast(req);
332 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
333 struct mv_cesa_engine *engine = creq->req.base.engine;
334 unsigned int digsize;
335 int ret, i;
336
db509a45
BB
337 if (creq->req.base.type == CESA_DMA_REQ)
338 ret = mv_cesa_dma_process(&creq->req.dma.base, status);
339 else
340 ret = mv_cesa_ahash_std_process(ahashreq, status);
341
f63601fd
BB
342 if (ret == -EINPROGRESS)
343 return ret;
344
345 digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
346 for (i = 0; i < digsize / 4; i++)
347 creq->state[i] = readl(engine->regs + CESA_IVDIG(i));
348
349 if (creq->cache_ptr)
350 sg_pcopy_to_buffer(ahashreq->src, creq->src_nents,
351 creq->cache,
352 creq->cache_ptr,
353 ahashreq->nbytes - creq->cache_ptr);
354
355 if (creq->last_req) {
4c2b130c
RK
356 /*
357 * Hardware's MD5 digest is in little endian format, but
358 * SHA in big endian format
359 */
a9eb678f 360 if (creq->algo_le) {
4c2b130c
RK
361 __le32 *result = (void *)ahashreq->result;
362
363 for (i = 0; i < digsize / 4; i++)
364 result[i] = cpu_to_le32(creq->state[i]);
365 } else {
366 __be32 *result = (void *)ahashreq->result;
f63601fd 367
4c2b130c
RK
368 for (i = 0; i < digsize / 4; i++)
369 result[i] = cpu_to_be32(creq->state[i]);
370 }
f63601fd
BB
371 }
372
373 return ret;
374}
375
376static void mv_cesa_ahash_prepare(struct crypto_async_request *req,
377 struct mv_cesa_engine *engine)
378{
379 struct ahash_request *ahashreq = ahash_request_cast(req);
380 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
381 unsigned int digsize;
382 int i;
383
384 creq->req.base.engine = engine;
385
db509a45
BB
386 if (creq->req.base.type == CESA_DMA_REQ)
387 mv_cesa_ahash_dma_prepare(ahashreq);
388 else
389 mv_cesa_ahash_std_prepare(ahashreq);
f63601fd
BB
390
391 digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
392 for (i = 0; i < digsize / 4; i++)
393 writel(creq->state[i],
394 engine->regs + CESA_IVDIG(i));
395}
396
397static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req)
398{
399 struct ahash_request *ahashreq = ahash_request_cast(req);
400 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
401
402 if (creq->last_req)
403 mv_cesa_ahash_last_cleanup(ahashreq);
db509a45
BB
404
405 mv_cesa_ahash_cleanup(ahashreq);
f63601fd
BB
406}
407
408static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = {
409 .step = mv_cesa_ahash_step,
410 .process = mv_cesa_ahash_process,
411 .prepare = mv_cesa_ahash_prepare,
412 .cleanup = mv_cesa_ahash_req_cleanup,
413};
414
415static int mv_cesa_ahash_init(struct ahash_request *req,
a9eb678f 416 struct mv_cesa_op_ctx *tmpl, bool algo_le)
f63601fd
BB
417{
418 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
419
420 memset(creq, 0, sizeof(*creq));
421 mv_cesa_update_op_cfg(tmpl,
422 CESA_SA_DESC_CFG_OP_MAC_ONLY |
423 CESA_SA_DESC_CFG_FIRST_FRAG,
424 CESA_SA_DESC_CFG_OP_MSK |
425 CESA_SA_DESC_CFG_FRAG_MSK);
426 mv_cesa_set_mac_op_total_len(tmpl, 0);
427 mv_cesa_set_mac_op_frag_len(tmpl, 0);
428 creq->op_tmpl = *tmpl;
429 creq->len = 0;
a9eb678f 430 creq->algo_le = algo_le;
f63601fd
BB
431
432 return 0;
433}
434
435static inline int mv_cesa_ahash_cra_init(struct crypto_tfm *tfm)
436{
437 struct mv_cesa_hash_ctx *ctx = crypto_tfm_ctx(tfm);
438
439 ctx->base.ops = &mv_cesa_ahash_req_ops;
440
441 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
442 sizeof(struct mv_cesa_ahash_req));
443 return 0;
444}
445
446static int mv_cesa_ahash_cache_req(struct ahash_request *req, bool *cached)
447{
448 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
449 int ret;
450
451 if (((creq->cache_ptr + req->nbytes) & CESA_HASH_BLOCK_SIZE_MSK) &&
452 !creq->last_req) {
453 ret = mv_cesa_ahash_alloc_cache(req);
454 if (ret)
455 return ret;
456 }
457
458 if (creq->cache_ptr + req->nbytes < 64 && !creq->last_req) {
459 *cached = true;
460
461 if (!req->nbytes)
462 return 0;
463
464 sg_pcopy_to_buffer(req->src, creq->src_nents,
465 creq->cache + creq->cache_ptr,
466 req->nbytes, 0);
467
468 creq->cache_ptr += req->nbytes;
469 }
470
471 return 0;
472}
473
db509a45
BB
474static struct mv_cesa_op_ctx *
475mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
476 struct mv_cesa_ahash_dma_iter *dma_iter,
477 struct mv_cesa_ahash_req *creq,
478 gfp_t flags)
479{
480 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
481 struct mv_cesa_op_ctx *op = NULL;
482 int ret;
483
484 if (!creq->cache_ptr)
485 return NULL;
486
487 ret = mv_cesa_dma_add_data_transfer(chain,
488 CESA_SA_DATA_SRAM_OFFSET,
489 ahashdreq->cache_dma,
490 creq->cache_ptr,
491 CESA_TDMA_DST_IN_SRAM,
492 flags);
493 if (ret)
494 return ERR_PTR(ret);
495
496 if (!dma_iter->base.op_len) {
497 op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
498 if (IS_ERR(op))
499 return op;
500
501 mv_cesa_set_mac_op_frag_len(op, creq->cache_ptr);
502
503 /* Add dummy desc to launch crypto operation */
504 ret = mv_cesa_dma_add_dummy_launch(chain, flags);
505 if (ret)
506 return ERR_PTR(ret);
507 }
508
509 return op;
510}
511
512static struct mv_cesa_op_ctx *
513mv_cesa_ahash_dma_add_data(struct mv_cesa_tdma_chain *chain,
514 struct mv_cesa_ahash_dma_iter *dma_iter,
515 struct mv_cesa_ahash_req *creq,
516 gfp_t flags)
517{
518 struct mv_cesa_op_ctx *op;
519 int ret;
520
521 op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
522 if (IS_ERR(op))
523 return op;
524
525 mv_cesa_set_mac_op_frag_len(op, dma_iter->base.op_len);
526
527 if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) ==
528 CESA_SA_DESC_CFG_FIRST_FRAG)
529 mv_cesa_update_op_cfg(&creq->op_tmpl,
530 CESA_SA_DESC_CFG_MID_FRAG,
531 CESA_SA_DESC_CFG_FRAG_MSK);
532
533 /* Add input transfers */
534 ret = mv_cesa_dma_add_op_transfers(chain, &dma_iter->base,
535 &dma_iter->src, flags);
536 if (ret)
537 return ERR_PTR(ret);
538
539 /* Add dummy desc to launch crypto operation */
540 ret = mv_cesa_dma_add_dummy_launch(chain, flags);
541 if (ret)
542 return ERR_PTR(ret);
543
544 return op;
545}
546
547static struct mv_cesa_op_ctx *
548mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
549 struct mv_cesa_ahash_dma_iter *dma_iter,
550 struct mv_cesa_ahash_req *creq,
551 struct mv_cesa_op_ctx *op,
552 gfp_t flags)
553{
554 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
555 unsigned int len, trailerlen, padoff = 0;
556 int ret;
557
558 if (!creq->last_req)
559 return op;
560
561 if (op && creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
562 u32 frag = CESA_SA_DESC_CFG_NOT_FRAG;
563
564 if ((mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) !=
565 CESA_SA_DESC_CFG_FIRST_FRAG)
566 frag = CESA_SA_DESC_CFG_LAST_FRAG;
567
568 mv_cesa_update_op_cfg(op, frag, CESA_SA_DESC_CFG_FRAG_MSK);
569
570 return op;
571 }
572
573 ret = mv_cesa_ahash_dma_alloc_padding(ahashdreq, flags);
574 if (ret)
575 return ERR_PTR(ret);
576
577 trailerlen = mv_cesa_ahash_pad_req(creq, ahashdreq->padding);
578
579 if (op) {
580 len = min(CESA_SA_SRAM_PAYLOAD_SIZE - dma_iter->base.op_len,
581 trailerlen);
582 if (len) {
583 ret = mv_cesa_dma_add_data_transfer(chain,
584 CESA_SA_DATA_SRAM_OFFSET +
585 dma_iter->base.op_len,
586 ahashdreq->padding_dma,
587 len, CESA_TDMA_DST_IN_SRAM,
588 flags);
589 if (ret)
590 return ERR_PTR(ret);
591
592 mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
593 CESA_SA_DESC_CFG_FRAG_MSK);
594 mv_cesa_set_mac_op_frag_len(op,
595 dma_iter->base.op_len + len);
596 padoff += len;
597 }
598 }
599
600 if (padoff >= trailerlen)
601 return op;
602
603 if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) !=
604 CESA_SA_DESC_CFG_FIRST_FRAG)
605 mv_cesa_update_op_cfg(&creq->op_tmpl,
606 CESA_SA_DESC_CFG_MID_FRAG,
607 CESA_SA_DESC_CFG_FRAG_MSK);
608
609 op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
610 if (IS_ERR(op))
611 return op;
612
613 mv_cesa_set_mac_op_frag_len(op, trailerlen - padoff);
614
615 ret = mv_cesa_dma_add_data_transfer(chain,
616 CESA_SA_DATA_SRAM_OFFSET,
617 ahashdreq->padding_dma +
618 padoff,
619 trailerlen - padoff,
620 CESA_TDMA_DST_IN_SRAM,
621 flags);
622 if (ret)
623 return ERR_PTR(ret);
624
625 /* Add dummy desc to launch crypto operation */
626 ret = mv_cesa_dma_add_dummy_launch(chain, flags);
627 if (ret)
628 return ERR_PTR(ret);
629
630 return op;
631}
632
633static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
634{
635 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
636 gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
637 GFP_KERNEL : GFP_ATOMIC;
638 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
639 struct mv_cesa_tdma_req *dreq = &ahashdreq->base;
640 struct mv_cesa_tdma_chain chain;
641 struct mv_cesa_ahash_dma_iter iter;
642 struct mv_cesa_op_ctx *op = NULL;
643 int ret;
644
645 dreq->chain.first = NULL;
646 dreq->chain.last = NULL;
647
648 if (creq->src_nents) {
649 ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents,
650 DMA_TO_DEVICE);
651 if (!ret) {
652 ret = -ENOMEM;
653 goto err;
654 }
655 }
656
657 mv_cesa_tdma_desc_iter_init(&chain);
658 mv_cesa_ahash_req_iter_init(&iter, req);
659
660 op = mv_cesa_ahash_dma_add_cache(&chain, &iter,
661 creq, flags);
662 if (IS_ERR(op)) {
663 ret = PTR_ERR(op);
664 goto err_free_tdma;
665 }
666
667 do {
668 if (!iter.base.op_len)
669 break;
670
671 op = mv_cesa_ahash_dma_add_data(&chain, &iter,
672 creq, flags);
673 if (IS_ERR(op)) {
674 ret = PTR_ERR(op);
675 goto err_free_tdma;
676 }
677 } while (mv_cesa_ahash_req_iter_next_op(&iter));
678
679 op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, op, flags);
680 if (IS_ERR(op)) {
681 ret = PTR_ERR(op);
682 goto err_free_tdma;
683 }
684
685 if (op) {
686 /* Add dummy desc to wait for crypto operation end */
687 ret = mv_cesa_dma_add_dummy_end(&chain, flags);
688 if (ret)
689 goto err_free_tdma;
690 }
691
692 if (!creq->last_req)
693 creq->cache_ptr = req->nbytes + creq->cache_ptr -
694 iter.base.len;
695 else
696 creq->cache_ptr = 0;
697
698 dreq->chain = chain;
699
700 return 0;
701
702err_free_tdma:
703 mv_cesa_dma_cleanup(dreq);
704 dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE);
705
706err:
707 mv_cesa_ahash_last_cleanup(req);
708
709 return ret;
710}
711
f63601fd
BB
712static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached)
713{
714 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
db509a45
BB
715 int ret;
716
717 if (cesa_dev->caps->has_tdma)
718 creq->req.base.type = CESA_DMA_REQ;
719 else
720 creq->req.base.type = CESA_STD_REQ;
f63601fd 721
f63601fd
BB
722 creq->src_nents = sg_nents_for_len(req->src, req->nbytes);
723
db509a45
BB
724 ret = mv_cesa_ahash_cache_req(req, cached);
725 if (ret)
726 return ret;
727
728 if (*cached)
729 return 0;
730
731 if (creq->req.base.type == CESA_DMA_REQ)
732 ret = mv_cesa_ahash_dma_req_init(req);
733
734 return ret;
f63601fd
BB
735}
736
737static int mv_cesa_ahash_update(struct ahash_request *req)
738{
739 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
740 bool cached = false;
741 int ret;
742
743 creq->len += req->nbytes;
744 ret = mv_cesa_ahash_req_init(req, &cached);
745 if (ret)
746 return ret;
747
748 if (cached)
749 return 0;
750
db509a45
BB
751 ret = mv_cesa_queue_req(&req->base);
752 if (ret && ret != -EINPROGRESS) {
753 mv_cesa_ahash_cleanup(req);
754 return ret;
755 }
756
757 return ret;
f63601fd
BB
758}
759
760static int mv_cesa_ahash_final(struct ahash_request *req)
761{
762 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
763 struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
764 bool cached = false;
765 int ret;
766
767 mv_cesa_set_mac_op_total_len(tmpl, creq->len);
768 creq->last_req = true;
769 req->nbytes = 0;
770
771 ret = mv_cesa_ahash_req_init(req, &cached);
772 if (ret)
773 return ret;
774
775 if (cached)
776 return 0;
777
db509a45
BB
778 ret = mv_cesa_queue_req(&req->base);
779 if (ret && ret != -EINPROGRESS)
780 mv_cesa_ahash_cleanup(req);
781
782 return ret;
f63601fd
BB
783}
784
785static int mv_cesa_ahash_finup(struct ahash_request *req)
786{
787 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
788 struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
789 bool cached = false;
790 int ret;
791
792 creq->len += req->nbytes;
793 mv_cesa_set_mac_op_total_len(tmpl, creq->len);
794 creq->last_req = true;
795
796 ret = mv_cesa_ahash_req_init(req, &cached);
797 if (ret)
798 return ret;
799
800 if (cached)
801 return 0;
802
db509a45
BB
803 ret = mv_cesa_queue_req(&req->base);
804 if (ret && ret != -EINPROGRESS)
805 mv_cesa_ahash_cleanup(req);
806
807 return ret;
f63601fd
BB
808}
809
a6479ea4
RK
810static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,
811 u64 *len, void *cache)
7aeef693 812{
7aeef693
AE
813 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
814 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
815 unsigned int digsize = crypto_ahash_digestsize(ahash);
a6479ea4 816 unsigned int blocksize;
7aeef693 817
80754539 818 blocksize = crypto_ahash_blocksize(ahash);
a6479ea4
RK
819
820 *len = creq->len;
821 memcpy(hash, creq->state, digsize);
822 memset(cache, 0, blocksize);
7aeef693 823 if (creq->cache)
a6479ea4 824 memcpy(cache, creq->cache, creq->cache_ptr);
7aeef693
AE
825
826 return 0;
827}
828
a6479ea4
RK
829static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash,
830 u64 len, const void *cache)
7aeef693 831{
7aeef693
AE
832 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
833 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
834 unsigned int digsize = crypto_ahash_digestsize(ahash);
a6479ea4 835 unsigned int blocksize;
7aeef693
AE
836 unsigned int cache_ptr;
837 int ret;
838
e72f407e
RK
839 ret = crypto_ahash_init(req);
840 if (ret)
841 return ret;
842
80754539 843 blocksize = crypto_ahash_blocksize(ahash);
a6479ea4 844 if (len >= blocksize)
c3bf02a2
RK
845 mv_cesa_update_op_cfg(&creq->op_tmpl,
846 CESA_SA_DESC_CFG_MID_FRAG,
847 CESA_SA_DESC_CFG_FRAG_MSK);
848
a6479ea4
RK
849 creq->len = len;
850 memcpy(creq->state, hash, digsize);
7aeef693
AE
851 creq->cache_ptr = 0;
852
a6479ea4 853 cache_ptr = do_div(len, blocksize);
7aeef693
AE
854 if (!cache_ptr)
855 return 0;
856
857 ret = mv_cesa_ahash_alloc_cache(req);
858 if (ret)
859 return ret;
860
a6479ea4 861 memcpy(creq->cache, cache, cache_ptr);
7aeef693
AE
862 creq->cache_ptr = cache_ptr;
863
864 return 0;
865}
866
a6479ea4
RK
867static int mv_cesa_md5_init(struct ahash_request *req)
868{
869 struct mv_cesa_op_ctx tmpl;
870
871 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
872
a9eb678f 873 mv_cesa_ahash_init(req, &tmpl, true);
a6479ea4
RK
874
875 return 0;
876}
877
878static int mv_cesa_md5_export(struct ahash_request *req, void *out)
879{
880 struct md5_state *out_state = out;
881
882 return mv_cesa_ahash_export(req, out_state->hash,
883 &out_state->byte_count, out_state->block);
884}
885
886static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
887{
888 const struct md5_state *in_state = in;
889
890 return mv_cesa_ahash_import(req, in_state->hash, in_state->byte_count,
891 in_state->block);
892}
893
7aeef693
AE
894static int mv_cesa_md5_digest(struct ahash_request *req)
895{
896 int ret;
897
898 ret = mv_cesa_md5_init(req);
899 if (ret)
900 return ret;
901
902 return mv_cesa_ahash_finup(req);
903}
904
905struct ahash_alg mv_md5_alg = {
906 .init = mv_cesa_md5_init,
907 .update = mv_cesa_ahash_update,
908 .final = mv_cesa_ahash_final,
909 .finup = mv_cesa_ahash_finup,
910 .digest = mv_cesa_md5_digest,
911 .export = mv_cesa_md5_export,
912 .import = mv_cesa_md5_import,
913 .halg = {
914 .digestsize = MD5_DIGEST_SIZE,
9f5594c9 915 .statesize = sizeof(struct md5_state),
7aeef693
AE
916 .base = {
917 .cra_name = "md5",
918 .cra_driver_name = "mv-md5",
919 .cra_priority = 300,
920 .cra_flags = CRYPTO_ALG_ASYNC |
921 CRYPTO_ALG_KERN_DRIVER_ONLY,
922 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
923 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx),
924 .cra_init = mv_cesa_ahash_cra_init,
925 .cra_module = THIS_MODULE,
926 }
927 }
928};
929
f63601fd
BB
930static int mv_cesa_sha1_init(struct ahash_request *req)
931{
932 struct mv_cesa_op_ctx tmpl;
933
934 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1);
935
a9eb678f 936 mv_cesa_ahash_init(req, &tmpl, false);
f63601fd
BB
937
938 return 0;
939}
940
941static int mv_cesa_sha1_export(struct ahash_request *req, void *out)
942{
943 struct sha1_state *out_state = out;
f63601fd 944
a6479ea4
RK
945 return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
946 out_state->buffer);
f63601fd
BB
947}
948
949static int mv_cesa_sha1_import(struct ahash_request *req, const void *in)
950{
951 const struct sha1_state *in_state = in;
f63601fd 952
a6479ea4
RK
953 return mv_cesa_ahash_import(req, in_state->state, in_state->count,
954 in_state->buffer);
f63601fd
BB
955}
956
957static int mv_cesa_sha1_digest(struct ahash_request *req)
958{
959 int ret;
960
961 ret = mv_cesa_sha1_init(req);
962 if (ret)
963 return ret;
964
965 return mv_cesa_ahash_finup(req);
966}
967
968struct ahash_alg mv_sha1_alg = {
969 .init = mv_cesa_sha1_init,
970 .update = mv_cesa_ahash_update,
971 .final = mv_cesa_ahash_final,
972 .finup = mv_cesa_ahash_finup,
973 .digest = mv_cesa_sha1_digest,
974 .export = mv_cesa_sha1_export,
975 .import = mv_cesa_sha1_import,
976 .halg = {
977 .digestsize = SHA1_DIGEST_SIZE,
9f5594c9 978 .statesize = sizeof(struct sha1_state),
f63601fd
BB
979 .base = {
980 .cra_name = "sha1",
981 .cra_driver_name = "mv-sha1",
982 .cra_priority = 300,
983 .cra_flags = CRYPTO_ALG_ASYNC |
984 CRYPTO_ALG_KERN_DRIVER_ONLY,
985 .cra_blocksize = SHA1_BLOCK_SIZE,
986 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx),
987 .cra_init = mv_cesa_ahash_cra_init,
988 .cra_module = THIS_MODULE,
989 }
990 }
991};
992
f85a762e
AE
993static int mv_cesa_sha256_init(struct ahash_request *req)
994{
995 struct mv_cesa_op_ctx tmpl;
996
997 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256);
998
a9eb678f 999 mv_cesa_ahash_init(req, &tmpl, false);
f85a762e
AE
1000
1001 return 0;
1002}
1003
1004static int mv_cesa_sha256_digest(struct ahash_request *req)
1005{
1006 int ret;
1007
1008 ret = mv_cesa_sha256_init(req);
1009 if (ret)
1010 return ret;
1011
1012 return mv_cesa_ahash_finup(req);
1013}
1014
1015static int mv_cesa_sha256_export(struct ahash_request *req, void *out)
1016{
1017 struct sha256_state *out_state = out;
f85a762e 1018
a6479ea4
RK
1019 return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
1020 out_state->buf);
f85a762e
AE
1021}
1022
1023static int mv_cesa_sha256_import(struct ahash_request *req, const void *in)
1024{
1025 const struct sha256_state *in_state = in;
c3bf02a2 1026
a6479ea4
RK
1027 return mv_cesa_ahash_import(req, in_state->state, in_state->count,
1028 in_state->buf);
f85a762e
AE
1029}
1030
1031struct ahash_alg mv_sha256_alg = {
1032 .init = mv_cesa_sha256_init,
1033 .update = mv_cesa_ahash_update,
1034 .final = mv_cesa_ahash_final,
1035 .finup = mv_cesa_ahash_finup,
1036 .digest = mv_cesa_sha256_digest,
1037 .export = mv_cesa_sha256_export,
1038 .import = mv_cesa_sha256_import,
1039 .halg = {
1040 .digestsize = SHA256_DIGEST_SIZE,
9f5594c9 1041 .statesize = sizeof(struct sha256_state),
f85a762e
AE
1042 .base = {
1043 .cra_name = "sha256",
1044 .cra_driver_name = "mv-sha256",
1045 .cra_priority = 300,
1046 .cra_flags = CRYPTO_ALG_ASYNC |
1047 CRYPTO_ALG_KERN_DRIVER_ONLY,
1048 .cra_blocksize = SHA256_BLOCK_SIZE,
1049 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx),
1050 .cra_init = mv_cesa_ahash_cra_init,
1051 .cra_module = THIS_MODULE,
1052 }
1053 }
1054};
1055
f63601fd
BB
1056struct mv_cesa_ahash_result {
1057 struct completion completion;
1058 int error;
1059};
1060
1061static void mv_cesa_hmac_ahash_complete(struct crypto_async_request *req,
1062 int error)
1063{
1064 struct mv_cesa_ahash_result *result = req->data;
1065
1066 if (error == -EINPROGRESS)
1067 return;
1068
1069 result->error = error;
1070 complete(&result->completion);
1071}
1072
1073static int mv_cesa_ahmac_iv_state_init(struct ahash_request *req, u8 *pad,
1074 void *state, unsigned int blocksize)
1075{
1076 struct mv_cesa_ahash_result result;
1077 struct scatterlist sg;
1078 int ret;
1079
1080 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1081 mv_cesa_hmac_ahash_complete, &result);
1082 sg_init_one(&sg, pad, blocksize);
1083 ahash_request_set_crypt(req, &sg, pad, blocksize);
1084 init_completion(&result.completion);
1085
1086 ret = crypto_ahash_init(req);
1087 if (ret)
1088 return ret;
1089
1090 ret = crypto_ahash_update(req);
1091 if (ret && ret != -EINPROGRESS)
1092 return ret;
1093
1094 wait_for_completion_interruptible(&result.completion);
1095 if (result.error)
1096 return result.error;
1097
1098 ret = crypto_ahash_export(req, state);
1099 if (ret)
1100 return ret;
1101
1102 return 0;
1103}
1104
1105static int mv_cesa_ahmac_pad_init(struct ahash_request *req,
1106 const u8 *key, unsigned int keylen,
1107 u8 *ipad, u8 *opad,
1108 unsigned int blocksize)
1109{
1110 struct mv_cesa_ahash_result result;
1111 struct scatterlist sg;
1112 int ret;
1113 int i;
1114
1115 if (keylen <= blocksize) {
1116 memcpy(ipad, key, keylen);
1117 } else {
1118 u8 *keydup = kmemdup(key, keylen, GFP_KERNEL);
1119
1120 if (!keydup)
1121 return -ENOMEM;
1122
1123 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1124 mv_cesa_hmac_ahash_complete,
1125 &result);
1126 sg_init_one(&sg, keydup, keylen);
1127 ahash_request_set_crypt(req, &sg, ipad, keylen);
1128 init_completion(&result.completion);
1129
1130 ret = crypto_ahash_digest(req);
1131 if (ret == -EINPROGRESS) {
1132 wait_for_completion_interruptible(&result.completion);
1133 ret = result.error;
1134 }
1135
1136 /* Set the memory region to 0 to avoid any leak. */
1137 memset(keydup, 0, keylen);
1138 kfree(keydup);
1139
1140 if (ret)
1141 return ret;
1142
1143 keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(req));
1144 }
1145
1146 memset(ipad + keylen, 0, blocksize - keylen);
1147 memcpy(opad, ipad, blocksize);
1148
1149 for (i = 0; i < blocksize; i++) {
1150 ipad[i] ^= 0x36;
1151 opad[i] ^= 0x5c;
1152 }
1153
1154 return 0;
1155}
1156
1157static int mv_cesa_ahmac_setkey(const char *hash_alg_name,
1158 const u8 *key, unsigned int keylen,
1159 void *istate, void *ostate)
1160{
1161 struct ahash_request *req;
1162 struct crypto_ahash *tfm;
1163 unsigned int blocksize;
1164 u8 *ipad = NULL;
1165 u8 *opad;
1166 int ret;
1167
1168 tfm = crypto_alloc_ahash(hash_alg_name, CRYPTO_ALG_TYPE_AHASH,
1169 CRYPTO_ALG_TYPE_AHASH_MASK);
1170 if (IS_ERR(tfm))
1171 return PTR_ERR(tfm);
1172
1173 req = ahash_request_alloc(tfm, GFP_KERNEL);
1174 if (!req) {
1175 ret = -ENOMEM;
1176 goto free_ahash;
1177 }
1178
1179 crypto_ahash_clear_flags(tfm, ~0);
1180
1181 blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1182
1183 ipad = kzalloc(2 * blocksize, GFP_KERNEL);
1184 if (!ipad) {
1185 ret = -ENOMEM;
1186 goto free_req;
1187 }
1188
1189 opad = ipad + blocksize;
1190
1191 ret = mv_cesa_ahmac_pad_init(req, key, keylen, ipad, opad, blocksize);
1192 if (ret)
1193 goto free_ipad;
1194
1195 ret = mv_cesa_ahmac_iv_state_init(req, ipad, istate, blocksize);
1196 if (ret)
1197 goto free_ipad;
1198
1199 ret = mv_cesa_ahmac_iv_state_init(req, opad, ostate, blocksize);
1200
1201free_ipad:
1202 kfree(ipad);
1203free_req:
1204 ahash_request_free(req);
1205free_ahash:
1206 crypto_free_ahash(tfm);
1207
1208 return ret;
1209}
1210
1211static int mv_cesa_ahmac_cra_init(struct crypto_tfm *tfm)
1212{
1213 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(tfm);
1214
1215 ctx->base.ops = &mv_cesa_ahash_req_ops;
1216
1217 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
1218 sizeof(struct mv_cesa_ahash_req));
1219 return 0;
1220}
1221
7aeef693
AE
1222static int mv_cesa_ahmac_md5_init(struct ahash_request *req)
1223{
1224 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1225 struct mv_cesa_op_ctx tmpl;
1226
1227 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_MD5);
1228 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
1229
a9eb678f 1230 mv_cesa_ahash_init(req, &tmpl, true);
7aeef693
AE
1231
1232 return 0;
1233}
1234
1235static int mv_cesa_ahmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1236 unsigned int keylen)
1237{
1238 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1239 struct md5_state istate, ostate;
1240 int ret, i;
1241
1242 ret = mv_cesa_ahmac_setkey("mv-md5", key, keylen, &istate, &ostate);
1243 if (ret)
1244 return ret;
1245
1246 for (i = 0; i < ARRAY_SIZE(istate.hash); i++)
1247 ctx->iv[i] = be32_to_cpu(istate.hash[i]);
1248
1249 for (i = 0; i < ARRAY_SIZE(ostate.hash); i++)
1250 ctx->iv[i + 8] = be32_to_cpu(ostate.hash[i]);
1251
1252 return 0;
1253}
1254
1255static int mv_cesa_ahmac_md5_digest(struct ahash_request *req)
1256{
1257 int ret;
1258
1259 ret = mv_cesa_ahmac_md5_init(req);
1260 if (ret)
1261 return ret;
1262
1263 return mv_cesa_ahash_finup(req);
1264}
1265
1266struct ahash_alg mv_ahmac_md5_alg = {
1267 .init = mv_cesa_ahmac_md5_init,
1268 .update = mv_cesa_ahash_update,
1269 .final = mv_cesa_ahash_final,
1270 .finup = mv_cesa_ahash_finup,
1271 .digest = mv_cesa_ahmac_md5_digest,
1272 .setkey = mv_cesa_ahmac_md5_setkey,
1273 .export = mv_cesa_md5_export,
1274 .import = mv_cesa_md5_import,
1275 .halg = {
1276 .digestsize = MD5_DIGEST_SIZE,
1277 .statesize = sizeof(struct md5_state),
1278 .base = {
1279 .cra_name = "hmac(md5)",
1280 .cra_driver_name = "mv-hmac-md5",
1281 .cra_priority = 300,
1282 .cra_flags = CRYPTO_ALG_ASYNC |
1283 CRYPTO_ALG_KERN_DRIVER_ONLY,
1284 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1285 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx),
1286 .cra_init = mv_cesa_ahmac_cra_init,
1287 .cra_module = THIS_MODULE,
1288 }
1289 }
1290};
1291
f63601fd
BB
1292static int mv_cesa_ahmac_sha1_init(struct ahash_request *req)
1293{
1294 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1295 struct mv_cesa_op_ctx tmpl;
1296
1297 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA1);
1298 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
1299
a9eb678f 1300 mv_cesa_ahash_init(req, &tmpl, false);
f63601fd
BB
1301
1302 return 0;
1303}
1304
1305static int mv_cesa_ahmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
1306 unsigned int keylen)
1307{
1308 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1309 struct sha1_state istate, ostate;
1310 int ret, i;
1311
1312 ret = mv_cesa_ahmac_setkey("mv-sha1", key, keylen, &istate, &ostate);
1313 if (ret)
1314 return ret;
1315
1316 for (i = 0; i < ARRAY_SIZE(istate.state); i++)
1317 ctx->iv[i] = be32_to_cpu(istate.state[i]);
1318
1319 for (i = 0; i < ARRAY_SIZE(ostate.state); i++)
1320 ctx->iv[i + 8] = be32_to_cpu(ostate.state[i]);
1321
1322 return 0;
1323}
1324
1325static int mv_cesa_ahmac_sha1_digest(struct ahash_request *req)
1326{
1327 int ret;
1328
1329 ret = mv_cesa_ahmac_sha1_init(req);
1330 if (ret)
1331 return ret;
1332
1333 return mv_cesa_ahash_finup(req);
1334}
1335
1336struct ahash_alg mv_ahmac_sha1_alg = {
1337 .init = mv_cesa_ahmac_sha1_init,
1338 .update = mv_cesa_ahash_update,
1339 .final = mv_cesa_ahash_final,
1340 .finup = mv_cesa_ahash_finup,
1341 .digest = mv_cesa_ahmac_sha1_digest,
1342 .setkey = mv_cesa_ahmac_sha1_setkey,
1343 .export = mv_cesa_sha1_export,
1344 .import = mv_cesa_sha1_import,
1345 .halg = {
1346 .digestsize = SHA1_DIGEST_SIZE,
1347 .statesize = sizeof(struct sha1_state),
1348 .base = {
1349 .cra_name = "hmac(sha1)",
1350 .cra_driver_name = "mv-hmac-sha1",
1351 .cra_priority = 300,
1352 .cra_flags = CRYPTO_ALG_ASYNC |
1353 CRYPTO_ALG_KERN_DRIVER_ONLY,
1354 .cra_blocksize = SHA1_BLOCK_SIZE,
1355 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx),
1356 .cra_init = mv_cesa_ahmac_cra_init,
1357 .cra_module = THIS_MODULE,
1358 }
1359 }
1360};
f85a762e
AE
1361
1362static int mv_cesa_ahmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
1363 unsigned int keylen)
1364{
1365 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1366 struct sha256_state istate, ostate;
1367 int ret, i;
1368
1369 ret = mv_cesa_ahmac_setkey("mv-sha256", key, keylen, &istate, &ostate);
1370 if (ret)
1371 return ret;
1372
1373 for (i = 0; i < ARRAY_SIZE(istate.state); i++)
1374 ctx->iv[i] = be32_to_cpu(istate.state[i]);
1375
1376 for (i = 0; i < ARRAY_SIZE(ostate.state); i++)
1377 ctx->iv[i + 8] = be32_to_cpu(ostate.state[i]);
1378
1379 return 0;
1380}
1381
1382static int mv_cesa_ahmac_sha256_init(struct ahash_request *req)
1383{
1384 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1385 struct mv_cesa_op_ctx tmpl;
1386
1387 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA256);
1388 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
1389
a9eb678f 1390 mv_cesa_ahash_init(req, &tmpl, false);
f85a762e
AE
1391
1392 return 0;
1393}
1394
1395static int mv_cesa_ahmac_sha256_digest(struct ahash_request *req)
1396{
1397 int ret;
1398
1399 ret = mv_cesa_ahmac_sha256_init(req);
1400 if (ret)
1401 return ret;
1402
1403 return mv_cesa_ahash_finup(req);
1404}
1405
1406struct ahash_alg mv_ahmac_sha256_alg = {
1407 .init = mv_cesa_ahmac_sha256_init,
1408 .update = mv_cesa_ahash_update,
1409 .final = mv_cesa_ahash_final,
1410 .finup = mv_cesa_ahash_finup,
1411 .digest = mv_cesa_ahmac_sha256_digest,
1412 .setkey = mv_cesa_ahmac_sha256_setkey,
1413 .export = mv_cesa_sha256_export,
1414 .import = mv_cesa_sha256_import,
1415 .halg = {
1416 .digestsize = SHA256_DIGEST_SIZE,
1417 .statesize = sizeof(struct sha256_state),
1418 .base = {
1419 .cra_name = "hmac(sha256)",
1420 .cra_driver_name = "mv-hmac-sha256",
1421 .cra_priority = 300,
1422 .cra_flags = CRYPTO_ALG_ASYNC |
1423 CRYPTO_ALG_KERN_DRIVER_ONLY,
1424 .cra_blocksize = SHA256_BLOCK_SIZE,
1425 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx),
1426 .cra_init = mv_cesa_ahmac_cra_init,
1427 .cra_module = THIS_MODULE,
1428 }
1429 }
1430};