blob: cb7af558b1760dad74ed46d13384189c2fcbf6ad [file] [log] [blame]
Yuan Kang045e3672012-06-22 19:48:47 -05001/*
2 * caam - Freescale FSL CAAM support for ahash functions of crypto API
3 *
4 * Copyright 2011 Freescale Semiconductor, Inc.
5 *
6 * Based on caamalg.c crypto API driver.
7 *
8 * relationship of digest job descriptor or first job descriptor after init to
9 * shared descriptors:
10 *
11 * --------------- ---------------
12 * | JobDesc #1 |-------------------->| ShareDesc |
13 * | *(packet 1) | | (hashKey) |
14 * --------------- | (operation) |
15 * ---------------
16 *
17 * relationship of subsequent job descriptors to shared descriptors:
18 *
19 * --------------- ---------------
20 * | JobDesc #2 |-------------------->| ShareDesc |
21 * | *(packet 2) | |------------->| (hashKey) |
22 * --------------- | |-------->| (operation) |
23 * . | | | (load ctx2) |
24 * . | | ---------------
25 * --------------- | |
26 * | JobDesc #3 |------| |
27 * | *(packet 3) | |
28 * --------------- |
29 * . |
30 * . |
31 * --------------- |
32 * | JobDesc #4 |------------
33 * | *(packet 4) |
34 * ---------------
35 *
36 * The SharedDesc never changes for a connection unless rekeyed, but
37 * each packet will likely be in a different place. So all we need
38 * to know to process the packet is where the input is, where the
39 * output goes, and what context we want to process with. Context is
40 * in the SharedDesc, packet references in the JobDesc.
41 *
42 * So, a job desc looks like:
43 *
44 * ---------------------
45 * | Header |
46 * | ShareDesc Pointer |
47 * | SEQ_OUT_PTR |
48 * | (output buffer) |
49 * | (output length) |
50 * | SEQ_IN_PTR |
51 * | (input buffer) |
52 * | (input length) |
53 * ---------------------
54 */
55
56#include "compat.h"
57
58#include "regs.h"
59#include "intern.h"
60#include "desc_constr.h"
61#include "jr.h"
62#include "error.h"
63#include "sg_sw_sec4.h"
64#include "key_gen.h"
65
66#define CAAM_CRA_PRIORITY 3000
67
68/* max hash key is max split key size */
69#define CAAM_MAX_HASH_KEY_SIZE (SHA512_DIGEST_SIZE * 2)
70
71#define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE
72#define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE
73
74/* length of descriptors text */
Yuan Kang045e3672012-06-22 19:48:47 -050075#define DESC_AHASH_BASE (4 * CAAM_CMD_SZ)
76#define DESC_AHASH_UPDATE_LEN (6 * CAAM_CMD_SZ)
77#define DESC_AHASH_UPDATE_FIRST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
78#define DESC_AHASH_FINAL_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ)
79#define DESC_AHASH_FINUP_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ)
80#define DESC_AHASH_DIGEST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
81
82#define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \
83 CAAM_MAX_HASH_KEY_SIZE)
84#define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ)
85
86/* caam context sizes for hashes: running digest + 8 */
87#define HASH_MSG_LEN 8
88#define MAX_CTX_LEN (HASH_MSG_LEN + SHA512_DIGEST_SIZE)
89
90#ifdef DEBUG
91/* for print_hex_dumps with line references */
Yuan Kang045e3672012-06-22 19:48:47 -050092#define debug(format, arg...) printk(format, arg)
93#else
94#define debug(format, arg...)
95#endif
96
Ruchika Guptacfc6f112013-10-25 12:01:03 +053097
98static struct list_head hash_list;
99
Yuan Kang045e3672012-06-22 19:48:47 -0500100/* ahash per-session context */
101struct caam_hash_ctx {
102 struct device *jrdev;
103 u32 sh_desc_update[DESC_HASH_MAX_USED_LEN];
104 u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN];
105 u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN];
106 u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN];
107 u32 sh_desc_finup[DESC_HASH_MAX_USED_LEN];
108 dma_addr_t sh_desc_update_dma;
109 dma_addr_t sh_desc_update_first_dma;
110 dma_addr_t sh_desc_fin_dma;
111 dma_addr_t sh_desc_digest_dma;
112 dma_addr_t sh_desc_finup_dma;
113 u32 alg_type;
114 u32 alg_op;
115 u8 key[CAAM_MAX_HASH_KEY_SIZE];
116 dma_addr_t key_dma;
117 int ctx_len;
118 unsigned int split_key_len;
119 unsigned int split_key_pad_len;
120};
121
122/* ahash state */
123struct caam_hash_state {
124 dma_addr_t buf_dma;
125 dma_addr_t ctx_dma;
126 u8 buf_0[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
127 int buflen_0;
128 u8 buf_1[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
129 int buflen_1;
Victoria Milhoane7472422015-08-05 11:28:35 -0700130 u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned;
Yuan Kang045e3672012-06-22 19:48:47 -0500131 int (*update)(struct ahash_request *req);
132 int (*final)(struct ahash_request *req);
133 int (*finup)(struct ahash_request *req);
134 int current_buf;
135};
136
137/* Common job descriptor seq in/out ptr routines */
138
139/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
Horia Geantace572082014-07-11 15:34:49 +0300140static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
141 struct caam_hash_state *state,
142 int ctx_len)
Yuan Kang045e3672012-06-22 19:48:47 -0500143{
144 state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
145 ctx_len, DMA_FROM_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +0300146 if (dma_mapping_error(jrdev, state->ctx_dma)) {
147 dev_err(jrdev, "unable to map ctx\n");
148 return -ENOMEM;
149 }
150
Yuan Kang045e3672012-06-22 19:48:47 -0500151 append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
Horia Geantace572082014-07-11 15:34:49 +0300152
153 return 0;
Yuan Kang045e3672012-06-22 19:48:47 -0500154}
155
156/* Map req->result, and append seq_out_ptr command that points to it */
157static inline dma_addr_t map_seq_out_ptr_result(u32 *desc, struct device *jrdev,
158 u8 *result, int digestsize)
159{
160 dma_addr_t dst_dma;
161
162 dst_dma = dma_map_single(jrdev, result, digestsize, DMA_FROM_DEVICE);
163 append_seq_out_ptr(desc, dst_dma, digestsize, 0);
164
165 return dst_dma;
166}
167
168/* Map current buffer in state and put it in link table */
169static inline dma_addr_t buf_map_to_sec4_sg(struct device *jrdev,
170 struct sec4_sg_entry *sec4_sg,
171 u8 *buf, int buflen)
172{
173 dma_addr_t buf_dma;
174
175 buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
176 dma_to_sec4_sg_one(sec4_sg, buf_dma, buflen, 0);
177
178 return buf_dma;
179}
180
181/* Map req->src and put it in link table */
182static inline void src_map_to_sec4_sg(struct device *jrdev,
183 struct scatterlist *src, int src_nents,
LABBE Corentin13fb8fd2015-09-23 13:55:27 +0200184 struct sec4_sg_entry *sec4_sg)
Yuan Kang045e3672012-06-22 19:48:47 -0500185{
LABBE Corentin13fb8fd2015-09-23 13:55:27 +0200186 dma_map_sg(jrdev, src, src_nents, DMA_TO_DEVICE);
Yuan Kang045e3672012-06-22 19:48:47 -0500187 sg_to_sec4_sg_last(src, src_nents, sec4_sg, 0);
188}
189
190/*
191 * Only put buffer in link table if it contains data, which is possible,
192 * since a buffer has previously been used, and needs to be unmapped,
193 */
194static inline dma_addr_t
195try_buf_map_to_sec4_sg(struct device *jrdev, struct sec4_sg_entry *sec4_sg,
196 u8 *buf, dma_addr_t buf_dma, int buflen,
197 int last_buflen)
198{
199 if (buf_dma && !dma_mapping_error(jrdev, buf_dma))
200 dma_unmap_single(jrdev, buf_dma, last_buflen, DMA_TO_DEVICE);
201 if (buflen)
202 buf_dma = buf_map_to_sec4_sg(jrdev, sec4_sg, buf, buflen);
203 else
204 buf_dma = 0;
205
206 return buf_dma;
207}
208
209/* Map state->caam_ctx, and add it to link table */
Horia Geantace572082014-07-11 15:34:49 +0300210static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
211 struct caam_hash_state *state, int ctx_len,
212 struct sec4_sg_entry *sec4_sg, u32 flag)
Yuan Kang045e3672012-06-22 19:48:47 -0500213{
214 state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
Horia Geantace572082014-07-11 15:34:49 +0300215 if (dma_mapping_error(jrdev, state->ctx_dma)) {
216 dev_err(jrdev, "unable to map ctx\n");
217 return -ENOMEM;
218 }
219
Yuan Kang045e3672012-06-22 19:48:47 -0500220 dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
Horia Geantace572082014-07-11 15:34:49 +0300221
222 return 0;
Yuan Kang045e3672012-06-22 19:48:47 -0500223}
224
225/* Common shared descriptor commands */
226static inline void append_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
227{
228 append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
229 ctx->split_key_len, CLASS_2 |
230 KEY_DEST_MDHA_SPLIT | KEY_ENC);
231}
232
233/* Append key if it has been set */
234static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
235{
236 u32 *key_jump_cmd;
237
Kim Phillips61bb86b2012-07-13 17:49:28 -0500238 init_sh_desc(desc, HDR_SHARE_SERIAL);
Yuan Kang045e3672012-06-22 19:48:47 -0500239
240 if (ctx->split_key_len) {
241 /* Skip if already shared */
242 key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
243 JUMP_COND_SHRD);
244
245 append_key_ahash(desc, ctx);
246
247 set_jump_tgt_here(desc, key_jump_cmd);
248 }
249
250 /* Propagate errors from shared to job descriptor */
251 append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
252}
253
254/*
255 * For ahash read data from seqin following state->caam_ctx,
256 * and write resulting class2 context to seqout, which may be state->caam_ctx
257 * or req->result
258 */
259static inline void ahash_append_load_str(u32 *desc, int digestsize)
260{
261 /* Calculate remaining bytes to read */
262 append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
263
264 /* Read remaining bytes */
265 append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 |
266 FIFOLD_TYPE_MSG | KEY_VLF);
267
268 /* Store class2 context bytes */
269 append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
270 LDST_SRCDST_BYTE_CONTEXT);
271}
272
273/*
274 * For ahash update, final and finup, import context, read and write to seqout
275 */
276static inline void ahash_ctx_data_to_out(u32 *desc, u32 op, u32 state,
277 int digestsize,
278 struct caam_hash_ctx *ctx)
279{
280 init_sh_desc_key_ahash(desc, ctx);
281
282 /* Import context from software */
283 append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
284 LDST_CLASS_2_CCB | ctx->ctx_len);
285
286 /* Class 2 operation */
287 append_operation(desc, op | state | OP_ALG_ENCRYPT);
288
289 /*
290 * Load from buf and/or src and write to req->result or state->context
291 */
292 ahash_append_load_str(desc, digestsize);
293}
294
295/* For ahash firsts and digest, read and write to seqout */
296static inline void ahash_data_to_out(u32 *desc, u32 op, u32 state,
297 int digestsize, struct caam_hash_ctx *ctx)
298{
299 init_sh_desc_key_ahash(desc, ctx);
300
301 /* Class 2 operation */
302 append_operation(desc, op | state | OP_ALG_ENCRYPT);
303
304 /*
305 * Load from buf and/or src and write to req->result or state->context
306 */
307 ahash_append_load_str(desc, digestsize);
308}
309
310static int ahash_set_sh_desc(struct crypto_ahash *ahash)
311{
312 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
313 int digestsize = crypto_ahash_digestsize(ahash);
314 struct device *jrdev = ctx->jrdev;
315 u32 have_key = 0;
316 u32 *desc;
317
318 if (ctx->split_key_len)
319 have_key = OP_ALG_AAI_HMAC_PRECOMP;
320
321 /* ahash_update shared descriptor */
322 desc = ctx->sh_desc_update;
323
Kim Phillips61bb86b2012-07-13 17:49:28 -0500324 init_sh_desc(desc, HDR_SHARE_SERIAL);
Yuan Kang045e3672012-06-22 19:48:47 -0500325
326 /* Import context from software */
327 append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
328 LDST_CLASS_2_CCB | ctx->ctx_len);
329
330 /* Class 2 operation */
331 append_operation(desc, ctx->alg_type | OP_ALG_AS_UPDATE |
332 OP_ALG_ENCRYPT);
333
334 /* Load data and write to result or context */
335 ahash_append_load_str(desc, ctx->ctx_len);
336
337 ctx->sh_desc_update_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
338 DMA_TO_DEVICE);
339 if (dma_mapping_error(jrdev, ctx->sh_desc_update_dma)) {
340 dev_err(jrdev, "unable to map shared descriptor\n");
341 return -ENOMEM;
342 }
343#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300344 print_hex_dump(KERN_ERR,
345 "ahash update shdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500346 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
347#endif
348
349 /* ahash_update_first shared descriptor */
350 desc = ctx->sh_desc_update_first;
351
352 ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INIT,
353 ctx->ctx_len, ctx);
354
355 ctx->sh_desc_update_first_dma = dma_map_single(jrdev, desc,
356 desc_bytes(desc),
357 DMA_TO_DEVICE);
358 if (dma_mapping_error(jrdev, ctx->sh_desc_update_first_dma)) {
359 dev_err(jrdev, "unable to map shared descriptor\n");
360 return -ENOMEM;
361 }
362#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300363 print_hex_dump(KERN_ERR,
364 "ahash update first shdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500365 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
366#endif
367
368 /* ahash_final shared descriptor */
369 desc = ctx->sh_desc_fin;
370
371 ahash_ctx_data_to_out(desc, have_key | ctx->alg_type,
372 OP_ALG_AS_FINALIZE, digestsize, ctx);
373
374 ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
375 DMA_TO_DEVICE);
376 if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) {
377 dev_err(jrdev, "unable to map shared descriptor\n");
378 return -ENOMEM;
379 }
380#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300381 print_hex_dump(KERN_ERR, "ahash final shdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500382 DUMP_PREFIX_ADDRESS, 16, 4, desc,
383 desc_bytes(desc), 1);
384#endif
385
386 /* ahash_finup shared descriptor */
387 desc = ctx->sh_desc_finup;
388
389 ahash_ctx_data_to_out(desc, have_key | ctx->alg_type,
390 OP_ALG_AS_FINALIZE, digestsize, ctx);
391
392 ctx->sh_desc_finup_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
393 DMA_TO_DEVICE);
394 if (dma_mapping_error(jrdev, ctx->sh_desc_finup_dma)) {
395 dev_err(jrdev, "unable to map shared descriptor\n");
396 return -ENOMEM;
397 }
398#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300399 print_hex_dump(KERN_ERR, "ahash finup shdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500400 DUMP_PREFIX_ADDRESS, 16, 4, desc,
401 desc_bytes(desc), 1);
402#endif
403
404 /* ahash_digest shared descriptor */
405 desc = ctx->sh_desc_digest;
406
407 ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INITFINAL,
408 digestsize, ctx);
409
410 ctx->sh_desc_digest_dma = dma_map_single(jrdev, desc,
411 desc_bytes(desc),
412 DMA_TO_DEVICE);
413 if (dma_mapping_error(jrdev, ctx->sh_desc_digest_dma)) {
414 dev_err(jrdev, "unable to map shared descriptor\n");
415 return -ENOMEM;
416 }
417#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300418 print_hex_dump(KERN_ERR,
419 "ahash digest shdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500420 DUMP_PREFIX_ADDRESS, 16, 4, desc,
421 desc_bytes(desc), 1);
422#endif
423
424 return 0;
425}
426
Kim Phillips66b3e882013-03-26 18:10:14 -0500427static int gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
Yuan Kang045e3672012-06-22 19:48:47 -0500428 u32 keylen)
429{
430 return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
431 ctx->split_key_pad_len, key_in, keylen,
432 ctx->alg_op);
433}
434
435/* Digest hash size if it is too large */
Kim Phillips66b3e882013-03-26 18:10:14 -0500436static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
Yuan Kang045e3672012-06-22 19:48:47 -0500437 u32 *keylen, u8 *key_out, u32 digestsize)
438{
439 struct device *jrdev = ctx->jrdev;
440 u32 *desc;
441 struct split_key_result result;
442 dma_addr_t src_dma, dst_dma;
443 int ret = 0;
444
Vakul Garg9c23b7d2013-07-10 06:26:13 +0000445 desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
Kim Phillips2af8f4a2012-09-07 04:17:03 +0800446 if (!desc) {
447 dev_err(jrdev, "unable to allocate key input memory\n");
448 return -ENOMEM;
449 }
Yuan Kang045e3672012-06-22 19:48:47 -0500450
451 init_job_desc(desc, 0);
452
453 src_dma = dma_map_single(jrdev, (void *)key_in, *keylen,
454 DMA_TO_DEVICE);
455 if (dma_mapping_error(jrdev, src_dma)) {
456 dev_err(jrdev, "unable to map key input memory\n");
457 kfree(desc);
458 return -ENOMEM;
459 }
460 dst_dma = dma_map_single(jrdev, (void *)key_out, digestsize,
461 DMA_FROM_DEVICE);
462 if (dma_mapping_error(jrdev, dst_dma)) {
463 dev_err(jrdev, "unable to map key output memory\n");
464 dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
465 kfree(desc);
466 return -ENOMEM;
467 }
468
469 /* Job descriptor to perform unkeyed hash on key_in */
470 append_operation(desc, ctx->alg_type | OP_ALG_ENCRYPT |
471 OP_ALG_AS_INITFINAL);
472 append_seq_in_ptr(desc, src_dma, *keylen, 0);
473 append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
474 FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
475 append_seq_out_ptr(desc, dst_dma, digestsize, 0);
476 append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
477 LDST_SRCDST_BYTE_CONTEXT);
478
479#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300480 print_hex_dump(KERN_ERR, "key_in@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500481 DUMP_PREFIX_ADDRESS, 16, 4, key_in, *keylen, 1);
Alex Porosanu514df282013-08-14 18:56:45 +0300482 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500483 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
484#endif
485
486 result.err = 0;
487 init_completion(&result.completion);
488
489 ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
490 if (!ret) {
491 /* in progress */
492 wait_for_completion_interruptible(&result.completion);
493 ret = result.err;
494#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300495 print_hex_dump(KERN_ERR,
496 "digested key@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500497 DUMP_PREFIX_ADDRESS, 16, 4, key_in,
498 digestsize, 1);
499#endif
500 }
Yuan Kang045e3672012-06-22 19:48:47 -0500501 dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
502 dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
503
Horia Geantae11aa9f2014-07-11 15:34:50 +0300504 *keylen = digestsize;
505
Yuan Kang045e3672012-06-22 19:48:47 -0500506 kfree(desc);
507
508 return ret;
509}
510
511static int ahash_setkey(struct crypto_ahash *ahash,
512 const u8 *key, unsigned int keylen)
513{
514 /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
515 static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
516 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
517 struct device *jrdev = ctx->jrdev;
518 int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
519 int digestsize = crypto_ahash_digestsize(ahash);
520 int ret = 0;
521 u8 *hashed_key = NULL;
522
523#ifdef DEBUG
524 printk(KERN_ERR "keylen %d\n", keylen);
525#endif
526
527 if (keylen > blocksize) {
528 hashed_key = kmalloc(sizeof(u8) * digestsize, GFP_KERNEL |
529 GFP_DMA);
530 if (!hashed_key)
531 return -ENOMEM;
532 ret = hash_digest_key(ctx, key, &keylen, hashed_key,
533 digestsize);
534 if (ret)
535 goto badkey;
536 key = hashed_key;
537 }
538
539 /* Pick class 2 key length from algorithm submask */
540 ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
541 OP_ALG_ALGSEL_SHIFT] * 2;
542 ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
543
544#ifdef DEBUG
545 printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
546 ctx->split_key_len, ctx->split_key_pad_len);
Alex Porosanu514df282013-08-14 18:56:45 +0300547 print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500548 DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
549#endif
550
551 ret = gen_split_hash_key(ctx, key, keylen);
552 if (ret)
553 goto badkey;
554
555 ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len,
556 DMA_TO_DEVICE);
557 if (dma_mapping_error(jrdev, ctx->key_dma)) {
558 dev_err(jrdev, "unable to map key i/o memory\n");
Horia Geanta3d67be22014-04-18 13:01:41 +0300559 ret = -ENOMEM;
560 goto map_err;
Yuan Kang045e3672012-06-22 19:48:47 -0500561 }
562#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300563 print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500564 DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
565 ctx->split_key_pad_len, 1);
566#endif
567
568 ret = ahash_set_sh_desc(ahash);
569 if (ret) {
570 dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len,
571 DMA_TO_DEVICE);
572 }
573
Horia Geanta3d67be22014-04-18 13:01:41 +0300574map_err:
Yuan Kang045e3672012-06-22 19:48:47 -0500575 kfree(hashed_key);
576 return ret;
577badkey:
578 kfree(hashed_key);
579 crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN);
580 return -EINVAL;
581}
582
583/*
584 * ahash_edesc - s/w-extended ahash descriptor
585 * @dst_dma: physical mapped address of req->result
586 * @sec4_sg_dma: physical mapped address of h/w link table
587 * @src_nents: number of segments in input scatterlist
588 * @sec4_sg_bytes: length of dma mapped sec4_sg space
589 * @sec4_sg: pointer to h/w link table
590 * @hw_desc: the h/w job descriptor followed by any referenced link tables
591 */
592struct ahash_edesc {
593 dma_addr_t dst_dma;
594 dma_addr_t sec4_sg_dma;
595 int src_nents;
596 int sec4_sg_bytes;
597 struct sec4_sg_entry *sec4_sg;
598 u32 hw_desc[0];
599};
600
601static inline void ahash_unmap(struct device *dev,
602 struct ahash_edesc *edesc,
603 struct ahash_request *req, int dst_len)
604{
605 if (edesc->src_nents)
LABBE Corentin13fb8fd2015-09-23 13:55:27 +0200606 dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
Yuan Kang045e3672012-06-22 19:48:47 -0500607 if (edesc->dst_dma)
608 dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE);
609
610 if (edesc->sec4_sg_bytes)
611 dma_unmap_single(dev, edesc->sec4_sg_dma,
612 edesc->sec4_sg_bytes, DMA_TO_DEVICE);
613}
614
615static inline void ahash_unmap_ctx(struct device *dev,
616 struct ahash_edesc *edesc,
617 struct ahash_request *req, int dst_len, u32 flag)
618{
619 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
620 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
621 struct caam_hash_state *state = ahash_request_ctx(req);
622
623 if (state->ctx_dma)
624 dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag);
625 ahash_unmap(dev, edesc, req, dst_len);
626}
627
628static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
629 void *context)
630{
631 struct ahash_request *req = context;
632 struct ahash_edesc *edesc;
633 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
634 int digestsize = crypto_ahash_digestsize(ahash);
635#ifdef DEBUG
636 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
637 struct caam_hash_state *state = ahash_request_ctx(req);
638
639 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
640#endif
641
642 edesc = (struct ahash_edesc *)((char *)desc -
643 offsetof(struct ahash_edesc, hw_desc));
Marek Vasutfa9659c2014-04-24 20:05:12 +0200644 if (err)
645 caam_jr_strstatus(jrdev, err);
Yuan Kang045e3672012-06-22 19:48:47 -0500646
647 ahash_unmap(jrdev, edesc, req, digestsize);
648 kfree(edesc);
649
650#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300651 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500652 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
653 ctx->ctx_len, 1);
654 if (req->result)
Alex Porosanu514df282013-08-14 18:56:45 +0300655 print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500656 DUMP_PREFIX_ADDRESS, 16, 4, req->result,
657 digestsize, 1);
658#endif
659
660 req->base.complete(&req->base, err);
661}
662
663static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err,
664 void *context)
665{
666 struct ahash_request *req = context;
667 struct ahash_edesc *edesc;
668 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
669 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
670#ifdef DEBUG
671 struct caam_hash_state *state = ahash_request_ctx(req);
672 int digestsize = crypto_ahash_digestsize(ahash);
673
674 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
675#endif
676
677 edesc = (struct ahash_edesc *)((char *)desc -
678 offsetof(struct ahash_edesc, hw_desc));
Marek Vasutfa9659c2014-04-24 20:05:12 +0200679 if (err)
680 caam_jr_strstatus(jrdev, err);
Yuan Kang045e3672012-06-22 19:48:47 -0500681
682 ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
683 kfree(edesc);
684
685#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300686 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500687 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
688 ctx->ctx_len, 1);
689 if (req->result)
Alex Porosanu514df282013-08-14 18:56:45 +0300690 print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500691 DUMP_PREFIX_ADDRESS, 16, 4, req->result,
692 digestsize, 1);
693#endif
694
695 req->base.complete(&req->base, err);
696}
697
698static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
699 void *context)
700{
701 struct ahash_request *req = context;
702 struct ahash_edesc *edesc;
703 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
704 int digestsize = crypto_ahash_digestsize(ahash);
705#ifdef DEBUG
706 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
707 struct caam_hash_state *state = ahash_request_ctx(req);
708
709 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
710#endif
711
712 edesc = (struct ahash_edesc *)((char *)desc -
713 offsetof(struct ahash_edesc, hw_desc));
Marek Vasutfa9659c2014-04-24 20:05:12 +0200714 if (err)
715 caam_jr_strstatus(jrdev, err);
Yuan Kang045e3672012-06-22 19:48:47 -0500716
Horia Geantabc9e05f2014-07-11 15:34:52 +0300717 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_TO_DEVICE);
Yuan Kang045e3672012-06-22 19:48:47 -0500718 kfree(edesc);
719
720#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300721 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500722 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
723 ctx->ctx_len, 1);
724 if (req->result)
Alex Porosanu514df282013-08-14 18:56:45 +0300725 print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500726 DUMP_PREFIX_ADDRESS, 16, 4, req->result,
727 digestsize, 1);
728#endif
729
730 req->base.complete(&req->base, err);
731}
732
733static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
734 void *context)
735{
736 struct ahash_request *req = context;
737 struct ahash_edesc *edesc;
738 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
739 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
740#ifdef DEBUG
741 struct caam_hash_state *state = ahash_request_ctx(req);
742 int digestsize = crypto_ahash_digestsize(ahash);
743
744 dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
745#endif
746
747 edesc = (struct ahash_edesc *)((char *)desc -
748 offsetof(struct ahash_edesc, hw_desc));
Marek Vasutfa9659c2014-04-24 20:05:12 +0200749 if (err)
750 caam_jr_strstatus(jrdev, err);
Yuan Kang045e3672012-06-22 19:48:47 -0500751
Horia Geantaef62b232014-07-11 15:34:51 +0300752 ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_FROM_DEVICE);
Yuan Kang045e3672012-06-22 19:48:47 -0500753 kfree(edesc);
754
755#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300756 print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500757 DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
758 ctx->ctx_len, 1);
759 if (req->result)
Alex Porosanu514df282013-08-14 18:56:45 +0300760 print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500761 DUMP_PREFIX_ADDRESS, 16, 4, req->result,
762 digestsize, 1);
763#endif
764
765 req->base.complete(&req->base, err);
766}
767
768/* submit update job descriptor */
769static int ahash_update_ctx(struct ahash_request *req)
770{
771 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
772 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
773 struct caam_hash_state *state = ahash_request_ctx(req);
774 struct device *jrdev = ctx->jrdev;
775 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
776 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
777 u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
778 int *buflen = state->current_buf ? &state->buflen_1 : &state->buflen_0;
779 u8 *next_buf = state->current_buf ? state->buf_0 : state->buf_1;
780 int *next_buflen = state->current_buf ? &state->buflen_0 :
781 &state->buflen_1, last_buflen;
782 int in_len = *buflen + req->nbytes, to_hash;
783 u32 *sh_desc = ctx->sh_desc_update, *desc;
784 dma_addr_t ptr = ctx->sh_desc_update_dma;
785 int src_nents, sec4_sg_bytes, sec4_sg_src_index;
786 struct ahash_edesc *edesc;
787 int ret = 0;
788 int sh_len;
789
790 last_buflen = *next_buflen;
791 *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1);
792 to_hash = in_len - *next_buflen;
793
794 if (to_hash) {
LABBE Corentin13fb8fd2015-09-23 13:55:27 +0200795 src_nents = sg_nents_for_len(req->src,
796 req->nbytes - (*next_buflen));
Yuan Kang045e3672012-06-22 19:48:47 -0500797 sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
798 sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
799 sizeof(struct sec4_sg_entry);
800
801 /*
802 * allocate space for base edesc and hw desc commands,
803 * link tables
804 */
Victoria Milhoandde20ae2015-08-05 11:28:39 -0700805 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN +
Yuan Kang045e3672012-06-22 19:48:47 -0500806 sec4_sg_bytes, GFP_DMA | flags);
807 if (!edesc) {
808 dev_err(jrdev,
809 "could not allocate extended descriptor\n");
810 return -ENOMEM;
811 }
812
813 edesc->src_nents = src_nents;
814 edesc->sec4_sg_bytes = sec4_sg_bytes;
815 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
816 DESC_JOB_IO_LEN;
Yuan Kang045e3672012-06-22 19:48:47 -0500817
Horia Geantace572082014-07-11 15:34:49 +0300818 ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
819 edesc->sec4_sg, DMA_BIDIRECTIONAL);
820 if (ret)
821 return ret;
Yuan Kang045e3672012-06-22 19:48:47 -0500822
823 state->buf_dma = try_buf_map_to_sec4_sg(jrdev,
824 edesc->sec4_sg + 1,
825 buf, state->buf_dma,
Victoria Milhoan7d5196ab2015-08-05 11:28:40 -0700826 *next_buflen, *buflen);
Yuan Kang045e3672012-06-22 19:48:47 -0500827
828 if (src_nents) {
829 src_map_to_sec4_sg(jrdev, req->src, src_nents,
LABBE Corentin13fb8fd2015-09-23 13:55:27 +0200830 edesc->sec4_sg + sec4_sg_src_index);
Victoria Milhoan8af7b0f2015-06-15 16:52:57 -0700831 if (*next_buflen)
Cristian Stoica307fd5432014-08-14 13:51:56 +0300832 scatterwalk_map_and_copy(next_buf, req->src,
833 to_hash - *buflen,
834 *next_buflen, 0);
Yuan Kang045e3672012-06-22 19:48:47 -0500835 } else {
836 (edesc->sec4_sg + sec4_sg_src_index - 1)->len |=
837 SEC4_SG_LEN_FIN;
838 }
839
Victoria Milhoan8af7b0f2015-06-15 16:52:57 -0700840 state->current_buf = !state->current_buf;
841
Yuan Kang045e3672012-06-22 19:48:47 -0500842 sh_len = desc_len(sh_desc);
843 desc = edesc->hw_desc;
844 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
845 HDR_REVERSE);
846
Ruchika Gupta1da2be32014-06-23 19:50:26 +0530847 edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
848 sec4_sg_bytes,
849 DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +0300850 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
851 dev_err(jrdev, "unable to map S/G table\n");
852 return -ENOMEM;
853 }
Ruchika Gupta1da2be32014-06-23 19:50:26 +0530854
Yuan Kang045e3672012-06-22 19:48:47 -0500855 append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
856 to_hash, LDST_SGF);
857
858 append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0);
859
860#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300861 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500862 DUMP_PREFIX_ADDRESS, 16, 4, desc,
863 desc_bytes(desc), 1);
864#endif
865
866 ret = caam_jr_enqueue(jrdev, desc, ahash_done_bi, req);
867 if (!ret) {
868 ret = -EINPROGRESS;
869 } else {
870 ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len,
871 DMA_BIDIRECTIONAL);
872 kfree(edesc);
873 }
874 } else if (*next_buflen) {
Cristian Stoica307fd5432014-08-14 13:51:56 +0300875 scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
876 req->nbytes, 0);
Yuan Kang045e3672012-06-22 19:48:47 -0500877 *buflen = *next_buflen;
878 *next_buflen = last_buflen;
879 }
880#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300881 print_hex_dump(KERN_ERR, "buf@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500882 DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1);
Alex Porosanu514df282013-08-14 18:56:45 +0300883 print_hex_dump(KERN_ERR, "next buf@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500884 DUMP_PREFIX_ADDRESS, 16, 4, next_buf,
885 *next_buflen, 1);
886#endif
887
888 return ret;
889}
890
891static int ahash_final_ctx(struct ahash_request *req)
892{
893 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
894 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
895 struct caam_hash_state *state = ahash_request_ctx(req);
896 struct device *jrdev = ctx->jrdev;
897 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
898 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
899 u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
900 int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
901 int last_buflen = state->current_buf ? state->buflen_0 :
902 state->buflen_1;
903 u32 *sh_desc = ctx->sh_desc_fin, *desc;
904 dma_addr_t ptr = ctx->sh_desc_fin_dma;
Horia Geant?b310c172015-08-11 20:19:20 +0300905 int sec4_sg_bytes, sec4_sg_src_index;
Yuan Kang045e3672012-06-22 19:48:47 -0500906 int digestsize = crypto_ahash_digestsize(ahash);
907 struct ahash_edesc *edesc;
908 int ret = 0;
909 int sh_len;
910
Horia Geant?b310c172015-08-11 20:19:20 +0300911 sec4_sg_src_index = 1 + (buflen ? 1 : 0);
912 sec4_sg_bytes = sec4_sg_src_index * sizeof(struct sec4_sg_entry);
Yuan Kang045e3672012-06-22 19:48:47 -0500913
914 /* allocate space for base edesc and hw desc commands, link tables */
Victoria Milhoandde20ae2015-08-05 11:28:39 -0700915 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN + sec4_sg_bytes,
916 GFP_DMA | flags);
Yuan Kang045e3672012-06-22 19:48:47 -0500917 if (!edesc) {
918 dev_err(jrdev, "could not allocate extended descriptor\n");
919 return -ENOMEM;
920 }
921
922 sh_len = desc_len(sh_desc);
923 desc = edesc->hw_desc;
924 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
925
926 edesc->sec4_sg_bytes = sec4_sg_bytes;
927 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
928 DESC_JOB_IO_LEN;
Yuan Kang045e3672012-06-22 19:48:47 -0500929 edesc->src_nents = 0;
930
Horia Geantace572082014-07-11 15:34:49 +0300931 ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
932 edesc->sec4_sg, DMA_TO_DEVICE);
933 if (ret)
934 return ret;
Yuan Kang045e3672012-06-22 19:48:47 -0500935
936 state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
937 buf, state->buf_dma, buflen,
938 last_buflen);
Horia Geant?b310c172015-08-11 20:19:20 +0300939 (edesc->sec4_sg + sec4_sg_src_index - 1)->len |= SEC4_SG_LEN_FIN;
Yuan Kang045e3672012-06-22 19:48:47 -0500940
Ruchika Gupta1da2be32014-06-23 19:50:26 +0530941 edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
942 sec4_sg_bytes, DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +0300943 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
944 dev_err(jrdev, "unable to map S/G table\n");
945 return -ENOMEM;
946 }
Ruchika Gupta1da2be32014-06-23 19:50:26 +0530947
Yuan Kang045e3672012-06-22 19:48:47 -0500948 append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
949 LDST_SGF);
950
951 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
952 digestsize);
Horia Geantace572082014-07-11 15:34:49 +0300953 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
954 dev_err(jrdev, "unable to map dst\n");
955 return -ENOMEM;
956 }
Yuan Kang045e3672012-06-22 19:48:47 -0500957
958#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +0300959 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -0500960 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
961#endif
962
963 ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req);
964 if (!ret) {
965 ret = -EINPROGRESS;
966 } else {
967 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
968 kfree(edesc);
969 }
970
971 return ret;
972}
973
974static int ahash_finup_ctx(struct ahash_request *req)
975{
976 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
977 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
978 struct caam_hash_state *state = ahash_request_ctx(req);
979 struct device *jrdev = ctx->jrdev;
980 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
981 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
982 u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
983 int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
984 int last_buflen = state->current_buf ? state->buflen_0 :
985 state->buflen_1;
986 u32 *sh_desc = ctx->sh_desc_finup, *desc;
987 dma_addr_t ptr = ctx->sh_desc_finup_dma;
988 int sec4_sg_bytes, sec4_sg_src_index;
989 int src_nents;
990 int digestsize = crypto_ahash_digestsize(ahash);
991 struct ahash_edesc *edesc;
992 int ret = 0;
993 int sh_len;
994
LABBE Corentin13fb8fd2015-09-23 13:55:27 +0200995 src_nents = sg_nents_for_len(req->src, req->nbytes);
Yuan Kang045e3672012-06-22 19:48:47 -0500996 sec4_sg_src_index = 1 + (buflen ? 1 : 0);
997 sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
998 sizeof(struct sec4_sg_entry);
999
1000 /* allocate space for base edesc and hw desc commands, link tables */
Victoria Milhoandde20ae2015-08-05 11:28:39 -07001001 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN + sec4_sg_bytes,
1002 GFP_DMA | flags);
Yuan Kang045e3672012-06-22 19:48:47 -05001003 if (!edesc) {
1004 dev_err(jrdev, "could not allocate extended descriptor\n");
1005 return -ENOMEM;
1006 }
1007
1008 sh_len = desc_len(sh_desc);
1009 desc = edesc->hw_desc;
1010 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
1011
1012 edesc->src_nents = src_nents;
1013 edesc->sec4_sg_bytes = sec4_sg_bytes;
1014 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
1015 DESC_JOB_IO_LEN;
Yuan Kang045e3672012-06-22 19:48:47 -05001016
Horia Geantace572082014-07-11 15:34:49 +03001017 ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
1018 edesc->sec4_sg, DMA_TO_DEVICE);
1019 if (ret)
1020 return ret;
Yuan Kang045e3672012-06-22 19:48:47 -05001021
1022 state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
1023 buf, state->buf_dma, buflen,
1024 last_buflen);
1025
1026 src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg +
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001027 sec4_sg_src_index);
Yuan Kang045e3672012-06-22 19:48:47 -05001028
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301029 edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
1030 sec4_sg_bytes, DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +03001031 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1032 dev_err(jrdev, "unable to map S/G table\n");
1033 return -ENOMEM;
1034 }
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301035
Yuan Kang045e3672012-06-22 19:48:47 -05001036 append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
1037 buflen + req->nbytes, LDST_SGF);
1038
1039 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
1040 digestsize);
Horia Geantace572082014-07-11 15:34:49 +03001041 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1042 dev_err(jrdev, "unable to map dst\n");
1043 return -ENOMEM;
1044 }
Yuan Kang045e3672012-06-22 19:48:47 -05001045
1046#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001047 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001048 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
1049#endif
1050
1051 ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req);
1052 if (!ret) {
1053 ret = -EINPROGRESS;
1054 } else {
1055 ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1056 kfree(edesc);
1057 }
1058
1059 return ret;
1060}
1061
1062static int ahash_digest(struct ahash_request *req)
1063{
1064 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1065 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1066 struct device *jrdev = ctx->jrdev;
1067 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
1068 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
1069 u32 *sh_desc = ctx->sh_desc_digest, *desc;
1070 dma_addr_t ptr = ctx->sh_desc_digest_dma;
1071 int digestsize = crypto_ahash_digestsize(ahash);
1072 int src_nents, sec4_sg_bytes;
1073 dma_addr_t src_dma;
1074 struct ahash_edesc *edesc;
1075 int ret = 0;
1076 u32 options;
1077 int sh_len;
1078
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001079 src_nents = sg_count(req->src, req->nbytes);
1080 dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE);
Yuan Kang045e3672012-06-22 19:48:47 -05001081 sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
1082
1083 /* allocate space for base edesc and hw desc commands, link tables */
Victoria Milhoandde20ae2015-08-05 11:28:39 -07001084 edesc = kzalloc(sizeof(*edesc) + sec4_sg_bytes + DESC_JOB_IO_LEN,
1085 GFP_DMA | flags);
Yuan Kang045e3672012-06-22 19:48:47 -05001086 if (!edesc) {
1087 dev_err(jrdev, "could not allocate extended descriptor\n");
1088 return -ENOMEM;
1089 }
1090 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
1091 DESC_JOB_IO_LEN;
Horia Geanta45e9af72014-07-11 15:34:53 +03001092 edesc->sec4_sg_bytes = sec4_sg_bytes;
Yuan Kang045e3672012-06-22 19:48:47 -05001093 edesc->src_nents = src_nents;
1094
1095 sh_len = desc_len(sh_desc);
1096 desc = edesc->hw_desc;
1097 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
1098
1099 if (src_nents) {
1100 sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301101 edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
1102 sec4_sg_bytes, DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +03001103 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1104 dev_err(jrdev, "unable to map S/G table\n");
1105 return -ENOMEM;
1106 }
Yuan Kang045e3672012-06-22 19:48:47 -05001107 src_dma = edesc->sec4_sg_dma;
1108 options = LDST_SGF;
1109 } else {
1110 src_dma = sg_dma_address(req->src);
1111 options = 0;
1112 }
1113 append_seq_in_ptr(desc, src_dma, req->nbytes, options);
1114
1115 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
1116 digestsize);
Horia Geantace572082014-07-11 15:34:49 +03001117 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1118 dev_err(jrdev, "unable to map dst\n");
1119 return -ENOMEM;
1120 }
Yuan Kang045e3672012-06-22 19:48:47 -05001121
1122#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001123 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001124 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
1125#endif
1126
1127 ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
1128 if (!ret) {
1129 ret = -EINPROGRESS;
1130 } else {
1131 ahash_unmap(jrdev, edesc, req, digestsize);
1132 kfree(edesc);
1133 }
1134
1135 return ret;
1136}
1137
1138/* submit ahash final if it the first job descriptor */
1139static int ahash_final_no_ctx(struct ahash_request *req)
1140{
1141 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1142 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1143 struct caam_hash_state *state = ahash_request_ctx(req);
1144 struct device *jrdev = ctx->jrdev;
1145 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
1146 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
1147 u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
1148 int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
1149 u32 *sh_desc = ctx->sh_desc_digest, *desc;
1150 dma_addr_t ptr = ctx->sh_desc_digest_dma;
1151 int digestsize = crypto_ahash_digestsize(ahash);
1152 struct ahash_edesc *edesc;
1153 int ret = 0;
1154 int sh_len;
1155
1156 /* allocate space for base edesc and hw desc commands, link tables */
Victoria Milhoandde20ae2015-08-05 11:28:39 -07001157 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN, GFP_DMA | flags);
Yuan Kang045e3672012-06-22 19:48:47 -05001158 if (!edesc) {
1159 dev_err(jrdev, "could not allocate extended descriptor\n");
1160 return -ENOMEM;
1161 }
1162
Yanjiang Jin060e2342015-03-06 10:34:41 +08001163 edesc->sec4_sg_bytes = 0;
Yuan Kang045e3672012-06-22 19:48:47 -05001164 sh_len = desc_len(sh_desc);
1165 desc = edesc->hw_desc;
1166 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
1167
1168 state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +03001169 if (dma_mapping_error(jrdev, state->buf_dma)) {
1170 dev_err(jrdev, "unable to map src\n");
1171 return -ENOMEM;
1172 }
Yuan Kang045e3672012-06-22 19:48:47 -05001173
1174 append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
1175
1176 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
1177 digestsize);
Horia Geantace572082014-07-11 15:34:49 +03001178 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1179 dev_err(jrdev, "unable to map dst\n");
1180 return -ENOMEM;
1181 }
Yuan Kang045e3672012-06-22 19:48:47 -05001182 edesc->src_nents = 0;
1183
1184#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001185 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001186 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
1187#endif
1188
1189 ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
1190 if (!ret) {
1191 ret = -EINPROGRESS;
1192 } else {
1193 ahash_unmap(jrdev, edesc, req, digestsize);
1194 kfree(edesc);
1195 }
1196
1197 return ret;
1198}
1199
1200/* submit ahash update if it the first job descriptor after update */
1201static int ahash_update_no_ctx(struct ahash_request *req)
1202{
1203 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1204 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1205 struct caam_hash_state *state = ahash_request_ctx(req);
1206 struct device *jrdev = ctx->jrdev;
1207 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
1208 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
1209 u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
1210 int *buflen = state->current_buf ? &state->buflen_1 : &state->buflen_0;
1211 u8 *next_buf = state->current_buf ? state->buf_0 : state->buf_1;
1212 int *next_buflen = state->current_buf ? &state->buflen_0 :
1213 &state->buflen_1;
1214 int in_len = *buflen + req->nbytes, to_hash;
1215 int sec4_sg_bytes, src_nents;
1216 struct ahash_edesc *edesc;
1217 u32 *desc, *sh_desc = ctx->sh_desc_update_first;
1218 dma_addr_t ptr = ctx->sh_desc_update_first_dma;
1219 int ret = 0;
1220 int sh_len;
1221
1222 *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1);
1223 to_hash = in_len - *next_buflen;
1224
1225 if (to_hash) {
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001226 src_nents = sg_nents_for_len(req->src,
1227 req->nbytes - (*next_buflen));
Yuan Kang045e3672012-06-22 19:48:47 -05001228 sec4_sg_bytes = (1 + src_nents) *
1229 sizeof(struct sec4_sg_entry);
1230
1231 /*
1232 * allocate space for base edesc and hw desc commands,
1233 * link tables
1234 */
Victoria Milhoandde20ae2015-08-05 11:28:39 -07001235 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN +
Yuan Kang045e3672012-06-22 19:48:47 -05001236 sec4_sg_bytes, GFP_DMA | flags);
1237 if (!edesc) {
1238 dev_err(jrdev,
1239 "could not allocate extended descriptor\n");
1240 return -ENOMEM;
1241 }
1242
1243 edesc->src_nents = src_nents;
1244 edesc->sec4_sg_bytes = sec4_sg_bytes;
1245 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
1246 DESC_JOB_IO_LEN;
Horia Geanta76b99082014-07-11 15:34:54 +03001247 edesc->dst_dma = 0;
Yuan Kang045e3672012-06-22 19:48:47 -05001248
1249 state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg,
1250 buf, *buflen);
1251 src_map_to_sec4_sg(jrdev, req->src, src_nents,
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001252 edesc->sec4_sg + 1);
Yuan Kang045e3672012-06-22 19:48:47 -05001253 if (*next_buflen) {
Cristian Stoica307fd5432014-08-14 13:51:56 +03001254 scatterwalk_map_and_copy(next_buf, req->src,
1255 to_hash - *buflen,
1256 *next_buflen, 0);
Yuan Kang045e3672012-06-22 19:48:47 -05001257 }
1258
Victoria Milhoan8af7b0f2015-06-15 16:52:57 -07001259 state->current_buf = !state->current_buf;
1260
Yuan Kang045e3672012-06-22 19:48:47 -05001261 sh_len = desc_len(sh_desc);
1262 desc = edesc->hw_desc;
1263 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
1264 HDR_REVERSE);
1265
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301266 edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
1267 sec4_sg_bytes,
1268 DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +03001269 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1270 dev_err(jrdev, "unable to map S/G table\n");
1271 return -ENOMEM;
1272 }
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301273
Yuan Kang045e3672012-06-22 19:48:47 -05001274 append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
1275
Horia Geantace572082014-07-11 15:34:49 +03001276 ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
1277 if (ret)
1278 return ret;
Yuan Kang045e3672012-06-22 19:48:47 -05001279
1280#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001281 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001282 DUMP_PREFIX_ADDRESS, 16, 4, desc,
1283 desc_bytes(desc), 1);
1284#endif
1285
1286 ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst, req);
1287 if (!ret) {
1288 ret = -EINPROGRESS;
1289 state->update = ahash_update_ctx;
1290 state->finup = ahash_finup_ctx;
1291 state->final = ahash_final_ctx;
1292 } else {
1293 ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len,
1294 DMA_TO_DEVICE);
1295 kfree(edesc);
1296 }
1297 } else if (*next_buflen) {
Cristian Stoica307fd5432014-08-14 13:51:56 +03001298 scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
1299 req->nbytes, 0);
Yuan Kang045e3672012-06-22 19:48:47 -05001300 *buflen = *next_buflen;
1301 *next_buflen = 0;
1302 }
1303#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001304 print_hex_dump(KERN_ERR, "buf@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001305 DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1);
Alex Porosanu514df282013-08-14 18:56:45 +03001306 print_hex_dump(KERN_ERR, "next buf@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001307 DUMP_PREFIX_ADDRESS, 16, 4, next_buf,
1308 *next_buflen, 1);
1309#endif
1310
1311 return ret;
1312}
1313
1314/* submit ahash finup if it the first job descriptor after update */
1315static int ahash_finup_no_ctx(struct ahash_request *req)
1316{
1317 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1318 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1319 struct caam_hash_state *state = ahash_request_ctx(req);
1320 struct device *jrdev = ctx->jrdev;
1321 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
1322 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
1323 u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
1324 int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
1325 int last_buflen = state->current_buf ? state->buflen_0 :
1326 state->buflen_1;
1327 u32 *sh_desc = ctx->sh_desc_digest, *desc;
1328 dma_addr_t ptr = ctx->sh_desc_digest_dma;
1329 int sec4_sg_bytes, sec4_sg_src_index, src_nents;
1330 int digestsize = crypto_ahash_digestsize(ahash);
1331 struct ahash_edesc *edesc;
1332 int sh_len;
1333 int ret = 0;
1334
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001335 src_nents = sg_nents_for_len(req->src, req->nbytes);
Yuan Kang045e3672012-06-22 19:48:47 -05001336 sec4_sg_src_index = 2;
1337 sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
1338 sizeof(struct sec4_sg_entry);
1339
1340 /* allocate space for base edesc and hw desc commands, link tables */
Victoria Milhoandde20ae2015-08-05 11:28:39 -07001341 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN + sec4_sg_bytes,
1342 GFP_DMA | flags);
Yuan Kang045e3672012-06-22 19:48:47 -05001343 if (!edesc) {
1344 dev_err(jrdev, "could not allocate extended descriptor\n");
1345 return -ENOMEM;
1346 }
1347
1348 sh_len = desc_len(sh_desc);
1349 desc = edesc->hw_desc;
1350 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
1351
1352 edesc->src_nents = src_nents;
1353 edesc->sec4_sg_bytes = sec4_sg_bytes;
1354 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
1355 DESC_JOB_IO_LEN;
Yuan Kang045e3672012-06-22 19:48:47 -05001356
1357 state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, buf,
1358 state->buf_dma, buflen,
1359 last_buflen);
1360
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001361 src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1);
Yuan Kang045e3672012-06-22 19:48:47 -05001362
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301363 edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
1364 sec4_sg_bytes, DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +03001365 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1366 dev_err(jrdev, "unable to map S/G table\n");
1367 return -ENOMEM;
1368 }
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301369
Yuan Kang045e3672012-06-22 19:48:47 -05001370 append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen +
1371 req->nbytes, LDST_SGF);
1372
1373 edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
1374 digestsize);
Horia Geantace572082014-07-11 15:34:49 +03001375 if (dma_mapping_error(jrdev, edesc->dst_dma)) {
1376 dev_err(jrdev, "unable to map dst\n");
1377 return -ENOMEM;
1378 }
Yuan Kang045e3672012-06-22 19:48:47 -05001379
1380#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001381 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001382 DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
1383#endif
1384
1385 ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
1386 if (!ret) {
1387 ret = -EINPROGRESS;
1388 } else {
1389 ahash_unmap(jrdev, edesc, req, digestsize);
1390 kfree(edesc);
1391 }
1392
1393 return ret;
1394}
1395
1396/* submit first update job descriptor after init */
1397static int ahash_update_first(struct ahash_request *req)
1398{
1399 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1400 struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1401 struct caam_hash_state *state = ahash_request_ctx(req);
1402 struct device *jrdev = ctx->jrdev;
1403 gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
1404 CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
Cristian Stoica4451d492014-08-14 13:51:57 +03001405 u8 *next_buf = state->current_buf ? state->buf_1 : state->buf_0;
1406 int *next_buflen = state->current_buf ?
1407 &state->buflen_1 : &state->buflen_0;
Yuan Kang045e3672012-06-22 19:48:47 -05001408 int to_hash;
1409 u32 *sh_desc = ctx->sh_desc_update_first, *desc;
1410 dma_addr_t ptr = ctx->sh_desc_update_first_dma;
1411 int sec4_sg_bytes, src_nents;
1412 dma_addr_t src_dma;
1413 u32 options;
1414 struct ahash_edesc *edesc;
1415 int ret = 0;
1416 int sh_len;
1417
1418 *next_buflen = req->nbytes & (crypto_tfm_alg_blocksize(&ahash->base) -
1419 1);
1420 to_hash = req->nbytes - *next_buflen;
1421
1422 if (to_hash) {
LABBE Corentin13fb8fd2015-09-23 13:55:27 +02001423 src_nents = sg_count(req->src, req->nbytes - (*next_buflen));
1424 dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE);
Yuan Kang045e3672012-06-22 19:48:47 -05001425 sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
1426
1427 /*
1428 * allocate space for base edesc and hw desc commands,
1429 * link tables
1430 */
Victoria Milhoandde20ae2015-08-05 11:28:39 -07001431 edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN +
Yuan Kang045e3672012-06-22 19:48:47 -05001432 sec4_sg_bytes, GFP_DMA | flags);
1433 if (!edesc) {
1434 dev_err(jrdev,
1435 "could not allocate extended descriptor\n");
1436 return -ENOMEM;
1437 }
1438
1439 edesc->src_nents = src_nents;
1440 edesc->sec4_sg_bytes = sec4_sg_bytes;
1441 edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
1442 DESC_JOB_IO_LEN;
Horia Geanta76b99082014-07-11 15:34:54 +03001443 edesc->dst_dma = 0;
Yuan Kang045e3672012-06-22 19:48:47 -05001444
1445 if (src_nents) {
1446 sg_to_sec4_sg_last(req->src, src_nents,
1447 edesc->sec4_sg, 0);
Ruchika Gupta1da2be32014-06-23 19:50:26 +05301448 edesc->sec4_sg_dma = dma_map_single(jrdev,
1449 edesc->sec4_sg,
1450 sec4_sg_bytes,
1451 DMA_TO_DEVICE);
Horia Geantace572082014-07-11 15:34:49 +03001452 if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1453 dev_err(jrdev, "unable to map S/G table\n");
1454 return -ENOMEM;
1455 }
Yuan Kang045e3672012-06-22 19:48:47 -05001456 src_dma = edesc->sec4_sg_dma;
1457 options = LDST_SGF;
1458 } else {
1459 src_dma = sg_dma_address(req->src);
1460 options = 0;
1461 }
1462
1463 if (*next_buflen)
Cristian Stoica307fd5432014-08-14 13:51:56 +03001464 scatterwalk_map_and_copy(next_buf, req->src, to_hash,
1465 *next_buflen, 0);
Yuan Kang045e3672012-06-22 19:48:47 -05001466
1467 sh_len = desc_len(sh_desc);
1468 desc = edesc->hw_desc;
1469 init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
1470 HDR_REVERSE);
1471
1472 append_seq_in_ptr(desc, src_dma, to_hash, options);
1473
Horia Geantace572082014-07-11 15:34:49 +03001474 ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
1475 if (ret)
1476 return ret;
Yuan Kang045e3672012-06-22 19:48:47 -05001477
1478#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001479 print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001480 DUMP_PREFIX_ADDRESS, 16, 4, desc,
1481 desc_bytes(desc), 1);
1482#endif
1483
1484 ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst,
1485 req);
1486 if (!ret) {
1487 ret = -EINPROGRESS;
1488 state->update = ahash_update_ctx;
1489 state->finup = ahash_finup_ctx;
1490 state->final = ahash_final_ctx;
1491 } else {
1492 ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len,
1493 DMA_TO_DEVICE);
1494 kfree(edesc);
1495 }
1496 } else if (*next_buflen) {
1497 state->update = ahash_update_no_ctx;
1498 state->finup = ahash_finup_no_ctx;
1499 state->final = ahash_final_no_ctx;
Cristian Stoica307fd5432014-08-14 13:51:56 +03001500 scatterwalk_map_and_copy(next_buf, req->src, 0,
1501 req->nbytes, 0);
Yuan Kang045e3672012-06-22 19:48:47 -05001502 }
1503#ifdef DEBUG
Alex Porosanu514df282013-08-14 18:56:45 +03001504 print_hex_dump(KERN_ERR, "next buf@"__stringify(__LINE__)": ",
Yuan Kang045e3672012-06-22 19:48:47 -05001505 DUMP_PREFIX_ADDRESS, 16, 4, next_buf,
1506 *next_buflen, 1);
1507#endif
1508
1509 return ret;
1510}
1511
1512static int ahash_finup_first(struct ahash_request *req)
1513{
1514 return ahash_digest(req);
1515}
1516
1517static int ahash_init(struct ahash_request *req)
1518{
1519 struct caam_hash_state *state = ahash_request_ctx(req);
1520
1521 state->update = ahash_update_first;
1522 state->finup = ahash_finup_first;
1523 state->final = ahash_final_no_ctx;
1524
1525 state->current_buf = 0;
Horia Geantade0e35e2014-07-11 15:34:55 +03001526 state->buf_dma = 0;
Steve Cornelius6fd4b152015-06-15 16:52:56 -07001527 state->buflen_0 = 0;
1528 state->buflen_1 = 0;
Yuan Kang045e3672012-06-22 19:48:47 -05001529
1530 return 0;
1531}
1532
1533static int ahash_update(struct ahash_request *req)
1534{
1535 struct caam_hash_state *state = ahash_request_ctx(req);
1536
1537 return state->update(req);
1538}
1539
1540static int ahash_finup(struct ahash_request *req)
1541{
1542 struct caam_hash_state *state = ahash_request_ctx(req);
1543
1544 return state->finup(req);
1545}
1546
1547static int ahash_final(struct ahash_request *req)
1548{
1549 struct caam_hash_state *state = ahash_request_ctx(req);
1550
1551 return state->final(req);
1552}
1553
1554static int ahash_export(struct ahash_request *req, void *out)
1555{
1556 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
Yuan Kang045e3672012-06-22 19:48:47 -05001557 struct caam_hash_state *state = ahash_request_ctx(req);
1558
Russell King434b4212015-10-18 17:51:15 +01001559 memcpy(out, state, sizeof(struct caam_hash_state));
1560
Yuan Kang045e3672012-06-22 19:48:47 -05001561 return 0;
1562}
1563
1564static int ahash_import(struct ahash_request *req, const void *in)
1565{
1566 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
Yuan Kang045e3672012-06-22 19:48:47 -05001567 struct caam_hash_state *state = ahash_request_ctx(req);
1568
Russell King434b4212015-10-18 17:51:15 +01001569 memcpy(state, in, sizeof(struct caam_hash_state));
1570
Yuan Kang045e3672012-06-22 19:48:47 -05001571 return 0;
1572}
1573
1574struct caam_hash_template {
1575 char name[CRYPTO_MAX_ALG_NAME];
1576 char driver_name[CRYPTO_MAX_ALG_NAME];
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001577 char hmac_name[CRYPTO_MAX_ALG_NAME];
1578 char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
Yuan Kang045e3672012-06-22 19:48:47 -05001579 unsigned int blocksize;
1580 struct ahash_alg template_ahash;
1581 u32 alg_type;
1582 u32 alg_op;
1583};
1584
1585/* ahash descriptors */
1586static struct caam_hash_template driver_hash[] = {
1587 {
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001588 .name = "sha1",
1589 .driver_name = "sha1-caam",
1590 .hmac_name = "hmac(sha1)",
1591 .hmac_driver_name = "hmac-sha1-caam",
Yuan Kang045e3672012-06-22 19:48:47 -05001592 .blocksize = SHA1_BLOCK_SIZE,
1593 .template_ahash = {
1594 .init = ahash_init,
1595 .update = ahash_update,
1596 .final = ahash_final,
1597 .finup = ahash_finup,
1598 .digest = ahash_digest,
1599 .export = ahash_export,
1600 .import = ahash_import,
1601 .setkey = ahash_setkey,
1602 .halg = {
1603 .digestsize = SHA1_DIGEST_SIZE,
1604 },
1605 },
1606 .alg_type = OP_ALG_ALGSEL_SHA1,
1607 .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
1608 }, {
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001609 .name = "sha224",
1610 .driver_name = "sha224-caam",
1611 .hmac_name = "hmac(sha224)",
1612 .hmac_driver_name = "hmac-sha224-caam",
Yuan Kang045e3672012-06-22 19:48:47 -05001613 .blocksize = SHA224_BLOCK_SIZE,
1614 .template_ahash = {
1615 .init = ahash_init,
1616 .update = ahash_update,
1617 .final = ahash_final,
1618 .finup = ahash_finup,
1619 .digest = ahash_digest,
1620 .export = ahash_export,
1621 .import = ahash_import,
1622 .setkey = ahash_setkey,
1623 .halg = {
1624 .digestsize = SHA224_DIGEST_SIZE,
1625 },
1626 },
1627 .alg_type = OP_ALG_ALGSEL_SHA224,
1628 .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
1629 }, {
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001630 .name = "sha256",
1631 .driver_name = "sha256-caam",
1632 .hmac_name = "hmac(sha256)",
1633 .hmac_driver_name = "hmac-sha256-caam",
Yuan Kang045e3672012-06-22 19:48:47 -05001634 .blocksize = SHA256_BLOCK_SIZE,
1635 .template_ahash = {
1636 .init = ahash_init,
1637 .update = ahash_update,
1638 .final = ahash_final,
1639 .finup = ahash_finup,
1640 .digest = ahash_digest,
1641 .export = ahash_export,
1642 .import = ahash_import,
1643 .setkey = ahash_setkey,
1644 .halg = {
1645 .digestsize = SHA256_DIGEST_SIZE,
1646 },
1647 },
1648 .alg_type = OP_ALG_ALGSEL_SHA256,
1649 .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
1650 }, {
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001651 .name = "sha384",
1652 .driver_name = "sha384-caam",
1653 .hmac_name = "hmac(sha384)",
1654 .hmac_driver_name = "hmac-sha384-caam",
Yuan Kang045e3672012-06-22 19:48:47 -05001655 .blocksize = SHA384_BLOCK_SIZE,
1656 .template_ahash = {
1657 .init = ahash_init,
1658 .update = ahash_update,
1659 .final = ahash_final,
1660 .finup = ahash_finup,
1661 .digest = ahash_digest,
1662 .export = ahash_export,
1663 .import = ahash_import,
1664 .setkey = ahash_setkey,
1665 .halg = {
1666 .digestsize = SHA384_DIGEST_SIZE,
1667 },
1668 },
1669 .alg_type = OP_ALG_ALGSEL_SHA384,
1670 .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
1671 }, {
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001672 .name = "sha512",
1673 .driver_name = "sha512-caam",
1674 .hmac_name = "hmac(sha512)",
1675 .hmac_driver_name = "hmac-sha512-caam",
Yuan Kang045e3672012-06-22 19:48:47 -05001676 .blocksize = SHA512_BLOCK_SIZE,
1677 .template_ahash = {
1678 .init = ahash_init,
1679 .update = ahash_update,
1680 .final = ahash_final,
1681 .finup = ahash_finup,
1682 .digest = ahash_digest,
1683 .export = ahash_export,
1684 .import = ahash_import,
1685 .setkey = ahash_setkey,
1686 .halg = {
1687 .digestsize = SHA512_DIGEST_SIZE,
1688 },
1689 },
1690 .alg_type = OP_ALG_ALGSEL_SHA512,
1691 .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
1692 }, {
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001693 .name = "md5",
1694 .driver_name = "md5-caam",
1695 .hmac_name = "hmac(md5)",
1696 .hmac_driver_name = "hmac-md5-caam",
Yuan Kang045e3672012-06-22 19:48:47 -05001697 .blocksize = MD5_BLOCK_WORDS * 4,
1698 .template_ahash = {
1699 .init = ahash_init,
1700 .update = ahash_update,
1701 .final = ahash_final,
1702 .finup = ahash_finup,
1703 .digest = ahash_digest,
1704 .export = ahash_export,
1705 .import = ahash_import,
1706 .setkey = ahash_setkey,
1707 .halg = {
1708 .digestsize = MD5_DIGEST_SIZE,
1709 },
1710 },
1711 .alg_type = OP_ALG_ALGSEL_MD5,
1712 .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
1713 },
1714};
1715
1716struct caam_hash_alg {
1717 struct list_head entry;
Yuan Kang045e3672012-06-22 19:48:47 -05001718 int alg_type;
1719 int alg_op;
1720 struct ahash_alg ahash_alg;
1721};
1722
1723static int caam_hash_cra_init(struct crypto_tfm *tfm)
1724{
1725 struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
1726 struct crypto_alg *base = tfm->__crt_alg;
1727 struct hash_alg_common *halg =
1728 container_of(base, struct hash_alg_common, base);
1729 struct ahash_alg *alg =
1730 container_of(halg, struct ahash_alg, halg);
1731 struct caam_hash_alg *caam_hash =
1732 container_of(alg, struct caam_hash_alg, ahash_alg);
1733 struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
Yuan Kang045e3672012-06-22 19:48:47 -05001734 /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
1735 static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
1736 HASH_MSG_LEN + SHA1_DIGEST_SIZE,
1737 HASH_MSG_LEN + 32,
1738 HASH_MSG_LEN + SHA256_DIGEST_SIZE,
1739 HASH_MSG_LEN + 64,
1740 HASH_MSG_LEN + SHA512_DIGEST_SIZE };
Yuan Kang045e3672012-06-22 19:48:47 -05001741 int ret = 0;
1742
1743 /*
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301744 * Get a Job ring from Job Ring driver to ensure in-order
Yuan Kang045e3672012-06-22 19:48:47 -05001745 * crypto request processing per tfm
1746 */
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301747 ctx->jrdev = caam_jr_alloc();
1748 if (IS_ERR(ctx->jrdev)) {
1749 pr_err("Job Ring Device allocation for transform failed\n");
1750 return PTR_ERR(ctx->jrdev);
1751 }
Yuan Kang045e3672012-06-22 19:48:47 -05001752 /* copy descriptor header template value */
1753 ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
1754 ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_hash->alg_op;
1755
1756 ctx->ctx_len = runninglen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
1757 OP_ALG_ALGSEL_SHIFT];
1758
1759 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
1760 sizeof(struct caam_hash_state));
1761
1762 ret = ahash_set_sh_desc(ahash);
1763
1764 return ret;
1765}
1766
1767static void caam_hash_cra_exit(struct crypto_tfm *tfm)
1768{
1769 struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
1770
1771 if (ctx->sh_desc_update_dma &&
1772 !dma_mapping_error(ctx->jrdev, ctx->sh_desc_update_dma))
1773 dma_unmap_single(ctx->jrdev, ctx->sh_desc_update_dma,
1774 desc_bytes(ctx->sh_desc_update),
1775 DMA_TO_DEVICE);
1776 if (ctx->sh_desc_update_first_dma &&
1777 !dma_mapping_error(ctx->jrdev, ctx->sh_desc_update_first_dma))
1778 dma_unmap_single(ctx->jrdev, ctx->sh_desc_update_first_dma,
1779 desc_bytes(ctx->sh_desc_update_first),
1780 DMA_TO_DEVICE);
1781 if (ctx->sh_desc_fin_dma &&
1782 !dma_mapping_error(ctx->jrdev, ctx->sh_desc_fin_dma))
1783 dma_unmap_single(ctx->jrdev, ctx->sh_desc_fin_dma,
1784 desc_bytes(ctx->sh_desc_fin), DMA_TO_DEVICE);
1785 if (ctx->sh_desc_digest_dma &&
1786 !dma_mapping_error(ctx->jrdev, ctx->sh_desc_digest_dma))
1787 dma_unmap_single(ctx->jrdev, ctx->sh_desc_digest_dma,
1788 desc_bytes(ctx->sh_desc_digest),
1789 DMA_TO_DEVICE);
1790 if (ctx->sh_desc_finup_dma &&
1791 !dma_mapping_error(ctx->jrdev, ctx->sh_desc_finup_dma))
1792 dma_unmap_single(ctx->jrdev, ctx->sh_desc_finup_dma,
1793 desc_bytes(ctx->sh_desc_finup), DMA_TO_DEVICE);
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301794
1795 caam_jr_free(ctx->jrdev);
Yuan Kang045e3672012-06-22 19:48:47 -05001796}
1797
1798static void __exit caam_algapi_hash_exit(void)
1799{
Yuan Kang045e3672012-06-22 19:48:47 -05001800 struct caam_hash_alg *t_alg, *n;
1801
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301802 if (!hash_list.next)
Yuan Kang045e3672012-06-22 19:48:47 -05001803 return;
1804
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301805 list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
Yuan Kang045e3672012-06-22 19:48:47 -05001806 crypto_unregister_ahash(&t_alg->ahash_alg);
1807 list_del(&t_alg->entry);
1808 kfree(t_alg);
1809 }
1810}
1811
1812static struct caam_hash_alg *
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301813caam_hash_alloc(struct caam_hash_template *template,
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001814 bool keyed)
Yuan Kang045e3672012-06-22 19:48:47 -05001815{
1816 struct caam_hash_alg *t_alg;
1817 struct ahash_alg *halg;
1818 struct crypto_alg *alg;
1819
Fabio Estevam9c4f9732015-08-21 13:52:00 -03001820 t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
Yuan Kang045e3672012-06-22 19:48:47 -05001821 if (!t_alg) {
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301822 pr_err("failed to allocate t_alg\n");
Yuan Kang045e3672012-06-22 19:48:47 -05001823 return ERR_PTR(-ENOMEM);
1824 }
1825
1826 t_alg->ahash_alg = template->template_ahash;
1827 halg = &t_alg->ahash_alg;
1828 alg = &halg->halg.base;
1829
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001830 if (keyed) {
1831 snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
1832 template->hmac_name);
1833 snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
1834 template->hmac_driver_name);
1835 } else {
1836 snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
1837 template->name);
1838 snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
1839 template->driver_name);
1840 }
Yuan Kang045e3672012-06-22 19:48:47 -05001841 alg->cra_module = THIS_MODULE;
1842 alg->cra_init = caam_hash_cra_init;
1843 alg->cra_exit = caam_hash_cra_exit;
1844 alg->cra_ctxsize = sizeof(struct caam_hash_ctx);
1845 alg->cra_priority = CAAM_CRA_PRIORITY;
1846 alg->cra_blocksize = template->blocksize;
1847 alg->cra_alignmask = 0;
1848 alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH;
1849 alg->cra_type = &crypto_ahash_type;
1850
1851 t_alg->alg_type = template->alg_type;
1852 t_alg->alg_op = template->alg_op;
Yuan Kang045e3672012-06-22 19:48:47 -05001853
1854 return t_alg;
1855}
1856
1857static int __init caam_algapi_hash_init(void)
1858{
Ruchika Gupta35af6402014-07-07 10:42:12 +05301859 struct device_node *dev_node;
1860 struct platform_device *pdev;
1861 struct device *ctrldev;
Yuan Kang045e3672012-06-22 19:48:47 -05001862 int i = 0, err = 0;
Victoria Milhoanbf834902015-08-05 11:28:48 -07001863 struct caam_drv_private *priv;
1864 unsigned int md_limit = SHA512_DIGEST_SIZE;
1865 u32 cha_inst, cha_vid;
Yuan Kang045e3672012-06-22 19:48:47 -05001866
Ruchika Gupta35af6402014-07-07 10:42:12 +05301867 dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
1868 if (!dev_node) {
1869 dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
1870 if (!dev_node)
1871 return -ENODEV;
1872 }
1873
1874 pdev = of_find_device_by_node(dev_node);
1875 if (!pdev) {
1876 of_node_put(dev_node);
1877 return -ENODEV;
1878 }
1879
1880 ctrldev = &pdev->dev;
1881 priv = dev_get_drvdata(ctrldev);
1882 of_node_put(dev_node);
1883
1884 /*
1885 * If priv is NULL, it's probably because the caam driver wasn't
1886 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
1887 */
1888 if (!priv)
1889 return -ENODEV;
1890
Victoria Milhoanbf834902015-08-05 11:28:48 -07001891 /*
1892 * Register crypto algorithms the device supports. First, identify
1893 * presence and attributes of MD block.
1894 */
1895 cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
1896 cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
1897
1898 /*
1899 * Skip registration of any hashing algorithms if MD block
1900 * is not present.
1901 */
1902 if (!((cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT))
1903 return -ENODEV;
1904
1905 /* Limit digest size based on LP256 */
1906 if ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256)
1907 md_limit = SHA256_DIGEST_SIZE;
1908
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301909 INIT_LIST_HEAD(&hash_list);
Yuan Kang045e3672012-06-22 19:48:47 -05001910
1911 /* register crypto algorithms the device supports */
1912 for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
Yuan Kang045e3672012-06-22 19:48:47 -05001913 struct caam_hash_alg *t_alg;
Victoria Milhoanbf834902015-08-05 11:28:48 -07001914 struct caam_hash_template *alg = driver_hash + i;
1915
1916 /* If MD size is not supported by device, skip registration */
1917 if (alg->template_ahash.halg.digestsize > md_limit)
1918 continue;
Yuan Kang045e3672012-06-22 19:48:47 -05001919
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001920 /* register hmac version */
Victoria Milhoanbf834902015-08-05 11:28:48 -07001921 t_alg = caam_hash_alloc(alg, true);
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001922 if (IS_ERR(t_alg)) {
1923 err = PTR_ERR(t_alg);
Victoria Milhoanbf834902015-08-05 11:28:48 -07001924 pr_warn("%s alg allocation failed\n", alg->driver_name);
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001925 continue;
1926 }
1927
1928 err = crypto_register_ahash(&t_alg->ahash_alg);
1929 if (err) {
Russell King6ea30f02015-10-18 17:51:10 +01001930 pr_warn("%s alg registration failed: %d\n",
1931 t_alg->ahash_alg.halg.base.cra_driver_name,
1932 err);
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001933 kfree(t_alg);
1934 } else
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301935 list_add_tail(&t_alg->entry, &hash_list);
Yuan Kangb0e09ba2012-06-22 19:48:48 -05001936
1937 /* register unkeyed version */
Victoria Milhoanbf834902015-08-05 11:28:48 -07001938 t_alg = caam_hash_alloc(alg, false);
Yuan Kang045e3672012-06-22 19:48:47 -05001939 if (IS_ERR(t_alg)) {
1940 err = PTR_ERR(t_alg);
Victoria Milhoanbf834902015-08-05 11:28:48 -07001941 pr_warn("%s alg allocation failed\n", alg->driver_name);
Yuan Kang045e3672012-06-22 19:48:47 -05001942 continue;
1943 }
1944
1945 err = crypto_register_ahash(&t_alg->ahash_alg);
1946 if (err) {
Russell King6ea30f02015-10-18 17:51:10 +01001947 pr_warn("%s alg registration failed: %d\n",
1948 t_alg->ahash_alg.halg.base.cra_driver_name,
1949 err);
Yuan Kang045e3672012-06-22 19:48:47 -05001950 kfree(t_alg);
1951 } else
Ruchika Guptacfc6f112013-10-25 12:01:03 +05301952 list_add_tail(&t_alg->entry, &hash_list);
Yuan Kang045e3672012-06-22 19:48:47 -05001953 }
1954
1955 return err;
1956}
1957
1958module_init(caam_algapi_hash_init);
1959module_exit(caam_algapi_hash_exit);
1960
1961MODULE_LICENSE("GPL");
1962MODULE_DESCRIPTION("FSL CAAM support for ahash functions of crypto API");
1963MODULE_AUTHOR("Freescale Semiconductor - NMG");