blob: d2a947ec1aebff51c8203e20b68a178c74238bdf [file] [log] [blame]
Boris BREZILLONf63601f2015-06-18 15:46:20 +02001/*
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
Arnaud Ebalard7aeef692015-06-18 15:46:24 +020015#include <crypto/md5.h>
Boris BREZILLONf63601f2015-06-18 15:46:20 +020016#include <crypto/sha.h>
17
18#include "cesa.h"
19
Boris BREZILLONdb509a42015-06-18 15:46:21 +020020struct 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
Boris BREZILLONf63601f2015-06-18 15:46:20 +020061static 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;
Boris BREZILLONdb509a42015-06-18 15:46:21 +020076 int ret;
Boris BREZILLONf63601f2015-06-18 15:46:20 +020077
78 if (creq->cache)
79 return 0;
80
Boris BREZILLONdb509a42015-06-18 15:46:21 +020081 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);
Boris BREZILLONf63601f2015-06-18 15:46:20 +020093}
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
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200105 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);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200109
110 creq->cache = NULL;
111}
112
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200113static 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
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200160static 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);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200165
166 if (creq->req.base.type == CESA_DMA_REQ)
167 mv_cesa_ahash_dma_last_cleanup(req);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200168}
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{
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200182 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);
Russell King51954a92015-10-18 17:23:46 +0100189
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 }
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200197
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
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200299static 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
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200307static 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);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200321 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200322
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200323 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);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200327}
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
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200337 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
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200342 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) {
Russell King4c2b1302015-10-18 17:23:35 +0100356 /*
357 * Hardware's MD5 digest is in little endian format, but
358 * SHA in big endian format
359 */
Russell Kinga9eb6782015-10-18 17:23:40 +0100360 if (creq->algo_le) {
Russell King4c2b1302015-10-18 17:23:35 +0100361 __le32 *result = (void *)ahashreq->result;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200362
Russell King4c2b1302015-10-18 17:23:35 +0100363 for (i = 0; i < digsize / 4; i++)
364 result[i] = cpu_to_le32(creq->state[i]);
365 } else {
366 __be32 *result = (void *)ahashreq->result;
367
368 for (i = 0; i < digsize / 4; i++)
369 result[i] = cpu_to_be32(creq->state[i]);
370 }
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200371 }
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
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200386 if (creq->req.base.type == CESA_DMA_REQ)
387 mv_cesa_ahash_dma_prepare(ahashreq);
388 else
389 mv_cesa_ahash_std_prepare(ahashreq);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200390
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);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200404
405 mv_cesa_ahash_cleanup(ahashreq);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200406}
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,
Russell Kinga9eb6782015-10-18 17:23:40 +0100416 struct mv_cesa_op_ctx *tmpl, bool algo_le)
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200417{
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;
Russell Kinga9eb6782015-10-18 17:23:40 +0100430 creq->algo_le = algo_le;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200431
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
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200474static struct mv_cesa_op_ctx *
Russell King96212882015-10-18 17:24:06 +0100475mv_cesa_dma_add_frag(struct mv_cesa_tdma_chain *chain,
476 struct mv_cesa_op_ctx *tmpl, unsigned int frag_len,
477 gfp_t flags)
478{
479 struct mv_cesa_op_ctx *op;
480 int ret;
481
482 op = mv_cesa_dma_add_op(chain, tmpl, false, flags);
483 if (IS_ERR(op))
484 return op;
485
486 /* Set the operation block fragment length. */
487 mv_cesa_set_mac_op_frag_len(op, frag_len);
488
489 /* Append dummy desc to launch operation */
490 ret = mv_cesa_dma_add_dummy_launch(chain, flags);
491 if (ret)
492 return ERR_PTR(ret);
493
Russell King2f396a92015-10-18 17:24:11 +0100494 if (mv_cesa_mac_op_is_first_frag(tmpl))
495 mv_cesa_update_op_cfg(tmpl,
496 CESA_SA_DESC_CFG_MID_FRAG,
497 CESA_SA_DESC_CFG_FRAG_MSK);
498
Russell King96212882015-10-18 17:24:06 +0100499 return op;
500}
501
Russell King0971d092015-10-18 17:24:16 +0100502static int
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200503mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
504 struct mv_cesa_ahash_dma_iter *dma_iter,
505 struct mv_cesa_ahash_req *creq,
506 gfp_t flags)
507{
508 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200509
510 if (!creq->cache_ptr)
Russell King0971d092015-10-18 17:24:16 +0100511 return 0;
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200512
Russell King0971d092015-10-18 17:24:16 +0100513 return mv_cesa_dma_add_data_transfer(chain,
514 CESA_SA_DATA_SRAM_OFFSET,
515 ahashdreq->cache_dma,
516 creq->cache_ptr,
517 CESA_TDMA_DST_IN_SRAM,
518 flags);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200519}
520
521static struct mv_cesa_op_ctx *
522mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
523 struct mv_cesa_ahash_dma_iter *dma_iter,
524 struct mv_cesa_ahash_req *creq,
525 struct mv_cesa_op_ctx *op,
526 gfp_t flags)
527{
528 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
529 unsigned int len, trailerlen, padoff = 0;
530 int ret;
531
532 if (!creq->last_req)
533 return op;
534
535 if (op && creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
536 u32 frag = CESA_SA_DESC_CFG_NOT_FRAG;
537
Russell King86517912015-10-18 17:24:01 +0100538 if (!mv_cesa_mac_op_is_first_frag(op))
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200539 frag = CESA_SA_DESC_CFG_LAST_FRAG;
540
541 mv_cesa_update_op_cfg(op, frag, CESA_SA_DESC_CFG_FRAG_MSK);
542
543 return op;
544 }
545
546 ret = mv_cesa_ahash_dma_alloc_padding(ahashdreq, flags);
547 if (ret)
548 return ERR_PTR(ret);
549
550 trailerlen = mv_cesa_ahash_pad_req(creq, ahashdreq->padding);
551
552 if (op) {
553 len = min(CESA_SA_SRAM_PAYLOAD_SIZE - dma_iter->base.op_len,
554 trailerlen);
555 if (len) {
556 ret = mv_cesa_dma_add_data_transfer(chain,
557 CESA_SA_DATA_SRAM_OFFSET +
558 dma_iter->base.op_len,
559 ahashdreq->padding_dma,
560 len, CESA_TDMA_DST_IN_SRAM,
561 flags);
562 if (ret)
563 return ERR_PTR(ret);
564
565 mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
566 CESA_SA_DESC_CFG_FRAG_MSK);
567 mv_cesa_set_mac_op_frag_len(op,
568 dma_iter->base.op_len + len);
569 padoff += len;
570 }
571 }
572
573 if (padoff >= trailerlen)
574 return op;
575
Russell King86517912015-10-18 17:24:01 +0100576 if (!mv_cesa_mac_op_is_first_frag(&creq->op_tmpl))
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200577 mv_cesa_update_op_cfg(&creq->op_tmpl,
578 CESA_SA_DESC_CFG_MID_FRAG,
579 CESA_SA_DESC_CFG_FRAG_MSK);
580
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200581 ret = mv_cesa_dma_add_data_transfer(chain,
582 CESA_SA_DATA_SRAM_OFFSET,
583 ahashdreq->padding_dma +
584 padoff,
585 trailerlen - padoff,
586 CESA_TDMA_DST_IN_SRAM,
587 flags);
588 if (ret)
589 return ERR_PTR(ret);
590
Russell King96212882015-10-18 17:24:06 +0100591 return mv_cesa_dma_add_frag(chain, &creq->op_tmpl, trailerlen - padoff,
592 flags);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200593}
594
595static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
596{
597 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
598 gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
599 GFP_KERNEL : GFP_ATOMIC;
600 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
601 struct mv_cesa_tdma_req *dreq = &ahashdreq->base;
602 struct mv_cesa_tdma_chain chain;
603 struct mv_cesa_ahash_dma_iter iter;
604 struct mv_cesa_op_ctx *op = NULL;
605 int ret;
606
607 dreq->chain.first = NULL;
608 dreq->chain.last = NULL;
609
610 if (creq->src_nents) {
611 ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents,
612 DMA_TO_DEVICE);
613 if (!ret) {
614 ret = -ENOMEM;
615 goto err;
616 }
617 }
618
619 mv_cesa_tdma_desc_iter_init(&chain);
620 mv_cesa_ahash_req_iter_init(&iter, req);
621
Russell King0971d092015-10-18 17:24:16 +0100622 /*
623 * Add the cache (left-over data from a previous block) first.
624 * This will never overflow the SRAM size.
625 */
626 ret = mv_cesa_ahash_dma_add_cache(&chain, &iter, creq, flags);
627 if (ret)
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200628 goto err_free_tdma;
Russell King0971d092015-10-18 17:24:16 +0100629
630 if (creq->cache_ptr && !iter.base.op_len) {
631 op = mv_cesa_dma_add_frag(&chain, &creq->op_tmpl,
632 creq->cache_ptr, flags);
633 if (IS_ERR(op)) {
634 ret = PTR_ERR(op);
635 goto err_free_tdma;
636 }
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200637 }
638
639 do {
640 if (!iter.base.op_len)
641 break;
642
Russell King0971d092015-10-18 17:24:16 +0100643 ret = mv_cesa_dma_add_op_transfers(&chain, &iter.base,
644 &iter.src, flags);
645 if (ret)
646 goto err_free_tdma;
647
648 op = mv_cesa_dma_add_frag(&chain, &creq->op_tmpl,
649 iter.base.op_len, flags);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200650 if (IS_ERR(op)) {
651 ret = PTR_ERR(op);
652 goto err_free_tdma;
653 }
654 } while (mv_cesa_ahash_req_iter_next_op(&iter));
655
656 op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, op, flags);
657 if (IS_ERR(op)) {
658 ret = PTR_ERR(op);
659 goto err_free_tdma;
660 }
661
662 if (op) {
663 /* Add dummy desc to wait for crypto operation end */
664 ret = mv_cesa_dma_add_dummy_end(&chain, flags);
665 if (ret)
666 goto err_free_tdma;
667 }
668
669 if (!creq->last_req)
670 creq->cache_ptr = req->nbytes + creq->cache_ptr -
671 iter.base.len;
672 else
673 creq->cache_ptr = 0;
674
675 dreq->chain = chain;
676
677 return 0;
678
679err_free_tdma:
680 mv_cesa_dma_cleanup(dreq);
681 dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE);
682
683err:
684 mv_cesa_ahash_last_cleanup(req);
685
686 return ret;
687}
688
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200689static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached)
690{
691 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200692 int ret;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200693
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200694 if (cesa_dev->caps->has_tdma)
695 creq->req.base.type = CESA_DMA_REQ;
696 else
697 creq->req.base.type = CESA_STD_REQ;
698
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200699 creq->src_nents = sg_nents_for_len(req->src, req->nbytes);
700
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200701 ret = mv_cesa_ahash_cache_req(req, cached);
702 if (ret)
703 return ret;
704
705 if (*cached)
706 return 0;
707
708 if (creq->req.base.type == CESA_DMA_REQ)
709 ret = mv_cesa_ahash_dma_req_init(req);
710
711 return ret;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200712}
713
714static int mv_cesa_ahash_update(struct ahash_request *req)
715{
716 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
717 bool cached = false;
718 int ret;
719
720 creq->len += req->nbytes;
721 ret = mv_cesa_ahash_req_init(req, &cached);
722 if (ret)
723 return ret;
724
725 if (cached)
726 return 0;
727
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200728 ret = mv_cesa_queue_req(&req->base);
729 if (ret && ret != -EINPROGRESS) {
730 mv_cesa_ahash_cleanup(req);
731 return ret;
732 }
733
734 return ret;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200735}
736
737static int mv_cesa_ahash_final(struct ahash_request *req)
738{
739 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
740 struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
741 bool cached = false;
742 int ret;
743
744 mv_cesa_set_mac_op_total_len(tmpl, creq->len);
745 creq->last_req = true;
746 req->nbytes = 0;
747
748 ret = mv_cesa_ahash_req_init(req, &cached);
749 if (ret)
750 return ret;
751
752 if (cached)
753 return 0;
754
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200755 ret = mv_cesa_queue_req(&req->base);
756 if (ret && ret != -EINPROGRESS)
757 mv_cesa_ahash_cleanup(req);
758
759 return ret;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200760}
761
762static int mv_cesa_ahash_finup(struct ahash_request *req)
763{
764 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
765 struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
766 bool cached = false;
767 int ret;
768
769 creq->len += req->nbytes;
770 mv_cesa_set_mac_op_total_len(tmpl, creq->len);
771 creq->last_req = true;
772
773 ret = mv_cesa_ahash_req_init(req, &cached);
774 if (ret)
775 return ret;
776
777 if (cached)
778 return 0;
779
Boris BREZILLONdb509a42015-06-18 15:46:21 +0200780 ret = mv_cesa_queue_req(&req->base);
781 if (ret && ret != -EINPROGRESS)
782 mv_cesa_ahash_cleanup(req);
783
784 return ret;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200785}
786
Russell Kinga6479ea2015-10-09 21:14:22 +0100787static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,
788 u64 *len, void *cache)
789{
790 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
791 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
792 unsigned int digsize = crypto_ahash_digestsize(ahash);
793 unsigned int blocksize;
794
Russell King80754532015-10-18 17:23:30 +0100795 blocksize = crypto_ahash_blocksize(ahash);
Russell Kinga6479ea2015-10-09 21:14:22 +0100796
797 *len = creq->len;
798 memcpy(hash, creq->state, digsize);
799 memset(cache, 0, blocksize);
800 if (creq->cache)
801 memcpy(cache, creq->cache, creq->cache_ptr);
802
803 return 0;
804}
805
806static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash,
807 u64 len, const void *cache)
808{
809 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
810 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
811 unsigned int digsize = crypto_ahash_digestsize(ahash);
812 unsigned int blocksize;
813 unsigned int cache_ptr;
814 int ret;
815
816 ret = crypto_ahash_init(req);
817 if (ret)
818 return ret;
819
Russell King80754532015-10-18 17:23:30 +0100820 blocksize = crypto_ahash_blocksize(ahash);
Russell Kinga6479ea2015-10-09 21:14:22 +0100821 if (len >= blocksize)
822 mv_cesa_update_op_cfg(&creq->op_tmpl,
823 CESA_SA_DESC_CFG_MID_FRAG,
824 CESA_SA_DESC_CFG_FRAG_MSK);
825
826 creq->len = len;
827 memcpy(creq->state, hash, digsize);
828 creq->cache_ptr = 0;
829
830 cache_ptr = do_div(len, blocksize);
831 if (!cache_ptr)
832 return 0;
833
834 ret = mv_cesa_ahash_alloc_cache(req);
835 if (ret)
836 return ret;
837
838 memcpy(creq->cache, cache, cache_ptr);
839 creq->cache_ptr = cache_ptr;
840
841 return 0;
842}
843
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200844static int mv_cesa_md5_init(struct ahash_request *req)
845{
Russell Kingd30cb2f2015-10-18 17:23:51 +0100846 struct mv_cesa_op_ctx tmpl = { };
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200847
848 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
849
Russell Kinga9eb6782015-10-18 17:23:40 +0100850 mv_cesa_ahash_init(req, &tmpl, true);
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200851
852 return 0;
853}
854
855static int mv_cesa_md5_export(struct ahash_request *req, void *out)
856{
857 struct md5_state *out_state = out;
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200858
Russell Kinga6479ea2015-10-09 21:14:22 +0100859 return mv_cesa_ahash_export(req, out_state->hash,
860 &out_state->byte_count, out_state->block);
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200861}
862
863static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
864{
865 const struct md5_state *in_state = in;
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200866
Russell Kinga6479ea2015-10-09 21:14:22 +0100867 return mv_cesa_ahash_import(req, in_state->hash, in_state->byte_count,
868 in_state->block);
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200869}
870
871static int mv_cesa_md5_digest(struct ahash_request *req)
872{
873 int ret;
874
875 ret = mv_cesa_md5_init(req);
876 if (ret)
877 return ret;
878
879 return mv_cesa_ahash_finup(req);
880}
881
882struct ahash_alg mv_md5_alg = {
883 .init = mv_cesa_md5_init,
884 .update = mv_cesa_ahash_update,
885 .final = mv_cesa_ahash_final,
886 .finup = mv_cesa_ahash_finup,
887 .digest = mv_cesa_md5_digest,
888 .export = mv_cesa_md5_export,
889 .import = mv_cesa_md5_import,
890 .halg = {
891 .digestsize = MD5_DIGEST_SIZE,
Russell King9f5594c2015-10-09 20:43:38 +0100892 .statesize = sizeof(struct md5_state),
Arnaud Ebalard7aeef692015-06-18 15:46:24 +0200893 .base = {
894 .cra_name = "md5",
895 .cra_driver_name = "mv-md5",
896 .cra_priority = 300,
897 .cra_flags = CRYPTO_ALG_ASYNC |
898 CRYPTO_ALG_KERN_DRIVER_ONLY,
899 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
900 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx),
901 .cra_init = mv_cesa_ahash_cra_init,
902 .cra_module = THIS_MODULE,
903 }
904 }
905};
906
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200907static int mv_cesa_sha1_init(struct ahash_request *req)
908{
Russell Kingd30cb2f2015-10-18 17:23:51 +0100909 struct mv_cesa_op_ctx tmpl = { };
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200910
911 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1);
912
Russell Kinga9eb6782015-10-18 17:23:40 +0100913 mv_cesa_ahash_init(req, &tmpl, false);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200914
915 return 0;
916}
917
918static int mv_cesa_sha1_export(struct ahash_request *req, void *out)
919{
920 struct sha1_state *out_state = out;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200921
Russell Kinga6479ea2015-10-09 21:14:22 +0100922 return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
923 out_state->buffer);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200924}
925
926static int mv_cesa_sha1_import(struct ahash_request *req, const void *in)
927{
928 const struct sha1_state *in_state = in;
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200929
Russell Kinga6479ea2015-10-09 21:14:22 +0100930 return mv_cesa_ahash_import(req, in_state->state, in_state->count,
931 in_state->buffer);
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200932}
933
934static int mv_cesa_sha1_digest(struct ahash_request *req)
935{
936 int ret;
937
938 ret = mv_cesa_sha1_init(req);
939 if (ret)
940 return ret;
941
942 return mv_cesa_ahash_finup(req);
943}
944
945struct ahash_alg mv_sha1_alg = {
946 .init = mv_cesa_sha1_init,
947 .update = mv_cesa_ahash_update,
948 .final = mv_cesa_ahash_final,
949 .finup = mv_cesa_ahash_finup,
950 .digest = mv_cesa_sha1_digest,
951 .export = mv_cesa_sha1_export,
952 .import = mv_cesa_sha1_import,
953 .halg = {
954 .digestsize = SHA1_DIGEST_SIZE,
Russell King9f5594c2015-10-09 20:43:38 +0100955 .statesize = sizeof(struct sha1_state),
Boris BREZILLONf63601f2015-06-18 15:46:20 +0200956 .base = {
957 .cra_name = "sha1",
958 .cra_driver_name = "mv-sha1",
959 .cra_priority = 300,
960 .cra_flags = CRYPTO_ALG_ASYNC |
961 CRYPTO_ALG_KERN_DRIVER_ONLY,
962 .cra_blocksize = SHA1_BLOCK_SIZE,
963 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx),
964 .cra_init = mv_cesa_ahash_cra_init,
965 .cra_module = THIS_MODULE,
966 }
967 }
968};
969
Arnaud Ebalardf85a7622015-06-18 15:46:25 +0200970static int mv_cesa_sha256_init(struct ahash_request *req)
971{
Russell Kingd30cb2f2015-10-18 17:23:51 +0100972 struct mv_cesa_op_ctx tmpl = { };
Arnaud Ebalardf85a7622015-06-18 15:46:25 +0200973
974 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256);
975
Russell Kinga9eb6782015-10-18 17:23:40 +0100976 mv_cesa_ahash_init(req, &tmpl, false);
Arnaud Ebalardf85a7622015-06-18 15:46:25 +0200977
978 return 0;
979}
980
981static int mv_cesa_sha256_digest(struct ahash_request *req)
982{
983 int ret;
984
985 ret = mv_cesa_sha256_init(req);
986 if (ret)
987 return ret;
988
989 return mv_cesa_ahash_finup(req);
990}
991
992static int mv_cesa_sha256_export(struct ahash_request *req, void *out)
993{
994 struct sha256_state *out_state = out;
Arnaud Ebalardf85a7622015-06-18 15:46:25 +0200995
Russell Kinga6479ea2015-10-09 21:14:22 +0100996 return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
997 out_state->buf);
Arnaud Ebalardf85a7622015-06-18 15:46:25 +0200998}
999
1000static int mv_cesa_sha256_import(struct ahash_request *req, const void *in)
1001{
1002 const struct sha256_state *in_state = in;
Arnaud Ebalardf85a7622015-06-18 15:46:25 +02001003
Russell Kinga6479ea2015-10-09 21:14:22 +01001004 return mv_cesa_ahash_import(req, in_state->state, in_state->count,
1005 in_state->buf);
Arnaud Ebalardf85a7622015-06-18 15:46:25 +02001006}
1007
1008struct ahash_alg mv_sha256_alg = {
1009 .init = mv_cesa_sha256_init,
1010 .update = mv_cesa_ahash_update,
1011 .final = mv_cesa_ahash_final,
1012 .finup = mv_cesa_ahash_finup,
1013 .digest = mv_cesa_sha256_digest,
1014 .export = mv_cesa_sha256_export,
1015 .import = mv_cesa_sha256_import,
1016 .halg = {
1017 .digestsize = SHA256_DIGEST_SIZE,
Russell King9f5594c2015-10-09 20:43:38 +01001018 .statesize = sizeof(struct sha256_state),
Arnaud Ebalardf85a7622015-06-18 15:46:25 +02001019 .base = {
1020 .cra_name = "sha256",
1021 .cra_driver_name = "mv-sha256",
1022 .cra_priority = 300,
1023 .cra_flags = CRYPTO_ALG_ASYNC |
1024 CRYPTO_ALG_KERN_DRIVER_ONLY,
1025 .cra_blocksize = SHA256_BLOCK_SIZE,
1026 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx),
1027 .cra_init = mv_cesa_ahash_cra_init,
1028 .cra_module = THIS_MODULE,
1029 }
1030 }
1031};
1032
Boris BREZILLONf63601f2015-06-18 15:46:20 +02001033struct mv_cesa_ahash_result {
1034 struct completion completion;
1035 int error;
1036};
1037
1038static void mv_cesa_hmac_ahash_complete(struct crypto_async_request *req,
1039 int error)
1040{
1041 struct mv_cesa_ahash_result *result = req->data;
1042
1043 if (error == -EINPROGRESS)
1044 return;
1045
1046 result->error = error;
1047 complete(&result->completion);
1048}
1049
1050static int mv_cesa_ahmac_iv_state_init(struct ahash_request *req, u8 *pad,
1051 void *state, unsigned int blocksize)
1052{
1053 struct mv_cesa_ahash_result result;
1054 struct scatterlist sg;
1055 int ret;
1056
1057 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1058 mv_cesa_hmac_ahash_complete, &result);
1059 sg_init_one(&sg, pad, blocksize);
1060 ahash_request_set_crypt(req, &sg, pad, blocksize);
1061 init_completion(&result.completion);
1062
1063 ret = crypto_ahash_init(req);
1064 if (ret)
1065 return ret;
1066
1067 ret = crypto_ahash_update(req);
1068 if (ret && ret != -EINPROGRESS)
1069 return ret;
1070
1071 wait_for_completion_interruptible(&result.completion);
1072 if (result.error)
1073 return result.error;
1074
1075 ret = crypto_ahash_export(req, state);
1076 if (ret)
1077 return ret;
1078
1079 return 0;
1080}
1081
1082static int mv_cesa_ahmac_pad_init(struct ahash_request *req,
1083 const u8 *key, unsigned int keylen,
1084 u8 *ipad, u8 *opad,
1085 unsigned int blocksize)
1086{
1087 struct mv_cesa_ahash_result result;
1088 struct scatterlist sg;
1089 int ret;
1090 int i;
1091
1092 if (keylen <= blocksize) {
1093 memcpy(ipad, key, keylen);
1094 } else {
1095 u8 *keydup = kmemdup(key, keylen, GFP_KERNEL);
1096
1097 if (!keydup)
1098 return -ENOMEM;
1099
1100 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1101 mv_cesa_hmac_ahash_complete,
1102 &result);
1103 sg_init_one(&sg, keydup, keylen);
1104 ahash_request_set_crypt(req, &sg, ipad, keylen);
1105 init_completion(&result.completion);
1106
1107 ret = crypto_ahash_digest(req);
1108 if (ret == -EINPROGRESS) {
1109 wait_for_completion_interruptible(&result.completion);
1110 ret = result.error;
1111 }
1112
1113 /* Set the memory region to 0 to avoid any leak. */
1114 memset(keydup, 0, keylen);
1115 kfree(keydup);
1116
1117 if (ret)
1118 return ret;
1119
1120 keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(req));
1121 }
1122
1123 memset(ipad + keylen, 0, blocksize - keylen);
1124 memcpy(opad, ipad, blocksize);
1125
1126 for (i = 0; i < blocksize; i++) {
1127 ipad[i] ^= 0x36;
1128 opad[i] ^= 0x5c;
1129 }
1130
1131 return 0;
1132}
1133
1134static int mv_cesa_ahmac_setkey(const char *hash_alg_name,
1135 const u8 *key, unsigned int keylen,
1136 void *istate, void *ostate)
1137{
1138 struct ahash_request *req;
1139 struct crypto_ahash *tfm;
1140 unsigned int blocksize;
1141 u8 *ipad = NULL;
1142 u8 *opad;
1143 int ret;
1144
1145 tfm = crypto_alloc_ahash(hash_alg_name, CRYPTO_ALG_TYPE_AHASH,
1146 CRYPTO_ALG_TYPE_AHASH_MASK);
1147 if (IS_ERR(tfm))
1148 return PTR_ERR(tfm);
1149
1150 req = ahash_request_alloc(tfm, GFP_KERNEL);
1151 if (!req) {
1152 ret = -ENOMEM;
1153 goto free_ahash;
1154 }
1155
1156 crypto_ahash_clear_flags(tfm, ~0);
1157
1158 blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1159
1160 ipad = kzalloc(2 * blocksize, GFP_KERNEL);
1161 if (!ipad) {
1162 ret = -ENOMEM;
1163 goto free_req;
1164 }
1165
1166 opad = ipad + blocksize;
1167
1168 ret = mv_cesa_ahmac_pad_init(req, key, keylen, ipad, opad, blocksize);
1169 if (ret)
1170 goto free_ipad;
1171
1172 ret = mv_cesa_ahmac_iv_state_init(req, ipad, istate, blocksize);
1173 if (ret)
1174 goto free_ipad;
1175
1176 ret = mv_cesa_ahmac_iv_state_init(req, opad, ostate, blocksize);
1177
1178free_ipad:
1179 kfree(ipad);
1180free_req:
1181 ahash_request_free(req);
1182free_ahash:
1183 crypto_free_ahash(tfm);
1184
1185 return ret;
1186}
1187
1188static int mv_cesa_ahmac_cra_init(struct crypto_tfm *tfm)
1189{
1190 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(tfm);
1191
1192 ctx->base.ops = &mv_cesa_ahash_req_ops;
1193
1194 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
1195 sizeof(struct mv_cesa_ahash_req));
1196 return 0;
1197}
1198
Arnaud Ebalard7aeef692015-06-18 15:46:24 +02001199static int mv_cesa_ahmac_md5_init(struct ahash_request *req)
1200{
1201 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
Russell Kingd30cb2f2015-10-18 17:23:51 +01001202 struct mv_cesa_op_ctx tmpl = { };
Arnaud Ebalard7aeef692015-06-18 15:46:24 +02001203
1204 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_MD5);
1205 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
1206
Russell Kinga9eb6782015-10-18 17:23:40 +01001207 mv_cesa_ahash_init(req, &tmpl, true);
Arnaud Ebalard7aeef692015-06-18 15:46:24 +02001208
1209 return 0;
1210}
1211
1212static int mv_cesa_ahmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key,
1213 unsigned int keylen)
1214{
1215 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1216 struct md5_state istate, ostate;
1217 int ret, i;
1218
1219 ret = mv_cesa_ahmac_setkey("mv-md5", key, keylen, &istate, &ostate);
1220 if (ret)
1221 return ret;
1222
1223 for (i = 0; i < ARRAY_SIZE(istate.hash); i++)
1224 ctx->iv[i] = be32_to_cpu(istate.hash[i]);
1225
1226 for (i = 0; i < ARRAY_SIZE(ostate.hash); i++)
1227 ctx->iv[i + 8] = be32_to_cpu(ostate.hash[i]);
1228
1229 return 0;
1230}
1231
1232static int mv_cesa_ahmac_md5_digest(struct ahash_request *req)
1233{
1234 int ret;
1235
1236 ret = mv_cesa_ahmac_md5_init(req);
1237 if (ret)
1238 return ret;
1239
1240 return mv_cesa_ahash_finup(req);
1241}
1242
1243struct ahash_alg mv_ahmac_md5_alg = {
1244 .init = mv_cesa_ahmac_md5_init,
1245 .update = mv_cesa_ahash_update,
1246 .final = mv_cesa_ahash_final,
1247 .finup = mv_cesa_ahash_finup,
1248 .digest = mv_cesa_ahmac_md5_digest,
1249 .setkey = mv_cesa_ahmac_md5_setkey,
1250 .export = mv_cesa_md5_export,
1251 .import = mv_cesa_md5_import,
1252 .halg = {
1253 .digestsize = MD5_DIGEST_SIZE,
1254 .statesize = sizeof(struct md5_state),
1255 .base = {
1256 .cra_name = "hmac(md5)",
1257 .cra_driver_name = "mv-hmac-md5",
1258 .cra_priority = 300,
1259 .cra_flags = CRYPTO_ALG_ASYNC |
1260 CRYPTO_ALG_KERN_DRIVER_ONLY,
1261 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
1262 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx),
1263 .cra_init = mv_cesa_ahmac_cra_init,
1264 .cra_module = THIS_MODULE,
1265 }
1266 }
1267};
1268
Boris BREZILLONf63601f2015-06-18 15:46:20 +02001269static int mv_cesa_ahmac_sha1_init(struct ahash_request *req)
1270{
1271 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
Russell Kingd30cb2f2015-10-18 17:23:51 +01001272 struct mv_cesa_op_ctx tmpl = { };
Boris BREZILLONf63601f2015-06-18 15:46:20 +02001273
1274 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA1);
1275 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
1276
Russell Kinga9eb6782015-10-18 17:23:40 +01001277 mv_cesa_ahash_init(req, &tmpl, false);
Boris BREZILLONf63601f2015-06-18 15:46:20 +02001278
1279 return 0;
1280}
1281
1282static int mv_cesa_ahmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key,
1283 unsigned int keylen)
1284{
1285 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1286 struct sha1_state istate, ostate;
1287 int ret, i;
1288
1289 ret = mv_cesa_ahmac_setkey("mv-sha1", key, keylen, &istate, &ostate);
1290 if (ret)
1291 return ret;
1292
1293 for (i = 0; i < ARRAY_SIZE(istate.state); i++)
1294 ctx->iv[i] = be32_to_cpu(istate.state[i]);
1295
1296 for (i = 0; i < ARRAY_SIZE(ostate.state); i++)
1297 ctx->iv[i + 8] = be32_to_cpu(ostate.state[i]);
1298
1299 return 0;
1300}
1301
1302static int mv_cesa_ahmac_sha1_digest(struct ahash_request *req)
1303{
1304 int ret;
1305
1306 ret = mv_cesa_ahmac_sha1_init(req);
1307 if (ret)
1308 return ret;
1309
1310 return mv_cesa_ahash_finup(req);
1311}
1312
1313struct ahash_alg mv_ahmac_sha1_alg = {
1314 .init = mv_cesa_ahmac_sha1_init,
1315 .update = mv_cesa_ahash_update,
1316 .final = mv_cesa_ahash_final,
1317 .finup = mv_cesa_ahash_finup,
1318 .digest = mv_cesa_ahmac_sha1_digest,
1319 .setkey = mv_cesa_ahmac_sha1_setkey,
1320 .export = mv_cesa_sha1_export,
1321 .import = mv_cesa_sha1_import,
1322 .halg = {
1323 .digestsize = SHA1_DIGEST_SIZE,
1324 .statesize = sizeof(struct sha1_state),
1325 .base = {
1326 .cra_name = "hmac(sha1)",
1327 .cra_driver_name = "mv-hmac-sha1",
1328 .cra_priority = 300,
1329 .cra_flags = CRYPTO_ALG_ASYNC |
1330 CRYPTO_ALG_KERN_DRIVER_ONLY,
1331 .cra_blocksize = SHA1_BLOCK_SIZE,
1332 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx),
1333 .cra_init = mv_cesa_ahmac_cra_init,
1334 .cra_module = THIS_MODULE,
1335 }
1336 }
1337};
Arnaud Ebalardf85a7622015-06-18 15:46:25 +02001338
1339static int mv_cesa_ahmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
1340 unsigned int keylen)
1341{
1342 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1343 struct sha256_state istate, ostate;
1344 int ret, i;
1345
1346 ret = mv_cesa_ahmac_setkey("mv-sha256", key, keylen, &istate, &ostate);
1347 if (ret)
1348 return ret;
1349
1350 for (i = 0; i < ARRAY_SIZE(istate.state); i++)
1351 ctx->iv[i] = be32_to_cpu(istate.state[i]);
1352
1353 for (i = 0; i < ARRAY_SIZE(ostate.state); i++)
1354 ctx->iv[i + 8] = be32_to_cpu(ostate.state[i]);
1355
1356 return 0;
1357}
1358
1359static int mv_cesa_ahmac_sha256_init(struct ahash_request *req)
1360{
1361 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
Russell Kingd30cb2f2015-10-18 17:23:51 +01001362 struct mv_cesa_op_ctx tmpl = { };
Arnaud Ebalardf85a7622015-06-18 15:46:25 +02001363
1364 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA256);
1365 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
1366
Russell Kinga9eb6782015-10-18 17:23:40 +01001367 mv_cesa_ahash_init(req, &tmpl, false);
Arnaud Ebalardf85a7622015-06-18 15:46:25 +02001368
1369 return 0;
1370}
1371
1372static int mv_cesa_ahmac_sha256_digest(struct ahash_request *req)
1373{
1374 int ret;
1375
1376 ret = mv_cesa_ahmac_sha256_init(req);
1377 if (ret)
1378 return ret;
1379
1380 return mv_cesa_ahash_finup(req);
1381}
1382
1383struct ahash_alg mv_ahmac_sha256_alg = {
1384 .init = mv_cesa_ahmac_sha256_init,
1385 .update = mv_cesa_ahash_update,
1386 .final = mv_cesa_ahash_final,
1387 .finup = mv_cesa_ahash_finup,
1388 .digest = mv_cesa_ahmac_sha256_digest,
1389 .setkey = mv_cesa_ahmac_sha256_setkey,
1390 .export = mv_cesa_sha256_export,
1391 .import = mv_cesa_sha256_import,
1392 .halg = {
1393 .digestsize = SHA256_DIGEST_SIZE,
1394 .statesize = sizeof(struct sha256_state),
1395 .base = {
1396 .cra_name = "hmac(sha256)",
1397 .cra_driver_name = "mv-hmac-sha256",
1398 .cra_priority = 300,
1399 .cra_flags = CRYPTO_ALG_ASYNC |
1400 CRYPTO_ALG_KERN_DRIVER_ONLY,
1401 .cra_blocksize = SHA256_BLOCK_SIZE,
1402 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx),
1403 .cra_init = mv_cesa_ahmac_cra_init,
1404 .cra_module = THIS_MODULE,
1405 }
1406 }
1407};