1// SPDX-License-Identifier: GPL-2.0-only
2// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3/*
4 * Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
5 */
6
7#include <linux/clk.h>
8#include <linux/dma-mapping.h>
9#include <linux/module.h>
10#include <linux/of_device.h>
11#include <linux/platform_device.h>
12
13#include <crypto/aes.h>
14#include <crypto/sha1.h>
15#include <crypto/sha2.h>
16#include <crypto/sha3.h>
17#include <crypto/internal/des.h>
18#include <crypto/engine.h>
19#include <crypto/scatterwalk.h>
20#include <crypto/internal/hash.h>
21
22#include "tegra-se.h"
23
24struct tegra_sha_ctx {
25	struct tegra_se *se;
26	unsigned int alg;
27	bool fallback;
28	u32 key_id;
29	struct crypto_ahash *fallback_tfm;
30};
31
32struct tegra_sha_reqctx {
33	struct scatterlist *src_sg;
34	struct tegra_se_datbuf datbuf;
35	struct tegra_se_datbuf residue;
36	struct tegra_se_datbuf digest;
37	unsigned int alg;
38	unsigned int config;
39	unsigned int total_len;
40	unsigned int blk_size;
41	unsigned int task;
42	u32 key_id;
43	u32 result[HASH_RESULT_REG_COUNT];
44	struct ahash_request fallback_req;
45};
46
47static int tegra_sha_get_config(u32 alg)
48{
49	int cfg = 0;
50
51	switch (alg) {
52	case SE_ALG_SHA1:
53		cfg |= SE_SHA_ENC_ALG_SHA;
54		cfg |= SE_SHA_ENC_MODE_SHA1;
55		break;
56
57	case SE_ALG_HMAC_SHA224:
58		cfg |= SE_SHA_ENC_ALG_HMAC;
59		fallthrough;
60	case SE_ALG_SHA224:
61		cfg |= SE_SHA_ENC_ALG_SHA;
62		cfg |= SE_SHA_ENC_MODE_SHA224;
63		break;
64
65	case SE_ALG_HMAC_SHA256:
66		cfg |= SE_SHA_ENC_ALG_HMAC;
67		fallthrough;
68	case SE_ALG_SHA256:
69		cfg |= SE_SHA_ENC_ALG_SHA;
70		cfg |= SE_SHA_ENC_MODE_SHA256;
71		break;
72
73	case SE_ALG_HMAC_SHA384:
74		cfg |= SE_SHA_ENC_ALG_HMAC;
75		fallthrough;
76	case SE_ALG_SHA384:
77		cfg |= SE_SHA_ENC_ALG_SHA;
78		cfg |= SE_SHA_ENC_MODE_SHA384;
79		break;
80
81	case SE_ALG_HMAC_SHA512:
82		cfg |= SE_SHA_ENC_ALG_HMAC;
83		fallthrough;
84	case SE_ALG_SHA512:
85		cfg |= SE_SHA_ENC_ALG_SHA;
86		cfg |= SE_SHA_ENC_MODE_SHA512;
87		break;
88
89	case SE_ALG_SHA3_224:
90		cfg |= SE_SHA_ENC_ALG_SHA;
91		cfg |= SE_SHA_ENC_MODE_SHA3_224;
92		break;
93	case SE_ALG_SHA3_256:
94		cfg |= SE_SHA_ENC_ALG_SHA;
95		cfg |= SE_SHA_ENC_MODE_SHA3_256;
96		break;
97	case SE_ALG_SHA3_384:
98		cfg |= SE_SHA_ENC_ALG_SHA;
99		cfg |= SE_SHA_ENC_MODE_SHA3_384;
100		break;
101	case SE_ALG_SHA3_512:
102		cfg |= SE_SHA_ENC_ALG_SHA;
103		cfg |= SE_SHA_ENC_MODE_SHA3_512;
104		break;
105	default:
106		return -EINVAL;
107	}
108
109	return cfg;
110}
111
112static int tegra_sha_fallback_init(struct ahash_request *req)
113{
114	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
115	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
116	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
117
118	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
119	rctx->fallback_req.base.flags = req->base.flags &
120					CRYPTO_TFM_REQ_MAY_SLEEP;
121
122	return crypto_ahash_init(&rctx->fallback_req);
123}
124
125static int tegra_sha_fallback_update(struct ahash_request *req)
126{
127	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
128	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
129	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
130
131	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
132	rctx->fallback_req.base.flags = req->base.flags &
133					CRYPTO_TFM_REQ_MAY_SLEEP;
134	rctx->fallback_req.nbytes = req->nbytes;
135	rctx->fallback_req.src = req->src;
136
137	return crypto_ahash_update(&rctx->fallback_req);
138}
139
140static int tegra_sha_fallback_final(struct ahash_request *req)
141{
142	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
143	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
144	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
145
146	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
147	rctx->fallback_req.base.flags = req->base.flags &
148					CRYPTO_TFM_REQ_MAY_SLEEP;
149	rctx->fallback_req.result = req->result;
150
151	return crypto_ahash_final(&rctx->fallback_req);
152}
153
154static int tegra_sha_fallback_finup(struct ahash_request *req)
155{
156	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
157	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
158	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
159
160	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
161	rctx->fallback_req.base.flags = req->base.flags &
162					CRYPTO_TFM_REQ_MAY_SLEEP;
163
164	rctx->fallback_req.nbytes = req->nbytes;
165	rctx->fallback_req.src = req->src;
166	rctx->fallback_req.result = req->result;
167
168	return crypto_ahash_finup(&rctx->fallback_req);
169}
170
171static int tegra_sha_fallback_digest(struct ahash_request *req)
172{
173	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
174	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
175	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
176
177	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
178	rctx->fallback_req.base.flags = req->base.flags &
179					CRYPTO_TFM_REQ_MAY_SLEEP;
180
181	rctx->fallback_req.nbytes = req->nbytes;
182	rctx->fallback_req.src = req->src;
183	rctx->fallback_req.result = req->result;
184
185	return crypto_ahash_digest(&rctx->fallback_req);
186}
187
188static int tegra_sha_fallback_import(struct ahash_request *req, const void *in)
189{
190	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
191	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
192	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
193
194	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
195	rctx->fallback_req.base.flags = req->base.flags &
196					CRYPTO_TFM_REQ_MAY_SLEEP;
197
198	return crypto_ahash_import(&rctx->fallback_req, in);
199}
200
201static int tegra_sha_fallback_export(struct ahash_request *req, void *out)
202{
203	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
204	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
205	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
206
207	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
208	rctx->fallback_req.base.flags = req->base.flags &
209					CRYPTO_TFM_REQ_MAY_SLEEP;
210
211	return crypto_ahash_export(&rctx->fallback_req, out);
212}
213
214static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
215			      struct tegra_sha_reqctx *rctx)
216{
217	u64 msg_len, msg_left;
218	int i = 0;
219
220	msg_len = rctx->total_len * 8;
221	msg_left = rctx->datbuf.size * 8;
222
223	/*
224	 * If IN_ADDR_HI_0.SZ > SHA_MSG_LEFT_[0-3] to the HASH engine,
225	 * HW treats it as the last buffer and process the data.
226	 * Therefore, add an extra byte to msg_left if it is not the
227	 * last buffer.
228	 */
229	if (rctx->task & SHA_UPDATE) {
230		msg_left += 8;
231		msg_len += 8;
232	}
233
234	cpuvaddr[i++] = host1x_opcode_setpayload(8);
235	cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_MSG_LENGTH);
236	cpuvaddr[i++] = lower_32_bits(msg_len);
237	cpuvaddr[i++] = upper_32_bits(msg_len);
238	cpuvaddr[i++] = 0;
239	cpuvaddr[i++] = 0;
240	cpuvaddr[i++] = lower_32_bits(msg_left);
241	cpuvaddr[i++] = upper_32_bits(msg_left);
242	cpuvaddr[i++] = 0;
243	cpuvaddr[i++] = 0;
244	cpuvaddr[i++] = host1x_opcode_setpayload(6);
245	cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_CFG);
246	cpuvaddr[i++] = rctx->config;
247
248	if (rctx->task & SHA_FIRST) {
249		cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT;
250		rctx->task &= ~SHA_FIRST;
251	} else {
252		cpuvaddr[i++] = 0;
253	}
254
255	cpuvaddr[i++] = rctx->datbuf.addr;
256	cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->datbuf.addr)) |
257				SE_ADDR_HI_SZ(rctx->datbuf.size));
258	cpuvaddr[i++] = rctx->digest.addr;
259	cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->digest.addr)) |
260				SE_ADDR_HI_SZ(rctx->digest.size));
261	if (rctx->key_id) {
262		cpuvaddr[i++] = host1x_opcode_setpayload(1);
263		cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
264		cpuvaddr[i++] = SE_AES_KEY_INDEX(rctx->key_id);
265	}
266
267	cpuvaddr[i++] = host1x_opcode_setpayload(1);
268	cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_OPERATION);
269	cpuvaddr[i++] = SE_SHA_OP_WRSTALL |
270			SE_SHA_OP_START |
271			SE_SHA_OP_LASTBUF;
272	cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
273	cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
274			host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
275
276	dev_dbg(se->dev, "msg len %llu msg left %llu cfg %#x",
277		msg_len, msg_left, rctx->config);
278
279	return i;
280}
281
282static void tegra_sha_copy_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
283{
284	int i;
285
286	for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
287		rctx->result[i] = readl(se->base + se->hw->regs->result + (i * 4));
288}
289
290static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
291{
292	int i;
293
294	for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
295		writel(rctx->result[i],
296		       se->base + se->hw->regs->result + (i * 4));
297}
298
299static int tegra_sha_do_update(struct ahash_request *req)
300{
301	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
302	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
303	unsigned int nblks, nresidue, size, ret;
304	u32 *cpuvaddr = ctx->se->cmdbuf->addr;
305
306	nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size;
307	nblks = (req->nbytes + rctx->residue.size) / rctx->blk_size;
308
309	/*
310	 * If nbytes is a multiple of block size and there is no residue,
311	 * then reserve the last block as residue during final() to process.
312	 */
313	if (!nresidue && nblks) {
314		nresidue = rctx->blk_size;
315		nblks--;
316	}
317
318	rctx->src_sg = req->src;
319	rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue;
320	rctx->total_len += rctx->datbuf.size;
321
322	/*
323	 * If nbytes are less than a block size, copy it residue and
324	 * return. The bytes will be processed in final()
325	 */
326	if (nblks < 1) {
327		scatterwalk_map_and_copy(rctx->residue.buf + rctx->residue.size,
328					 rctx->src_sg, 0, req->nbytes, 0);
329
330		rctx->residue.size += req->nbytes;
331		return 0;
332	}
333
334	/* Copy the previous residue first */
335	if (rctx->residue.size)
336		memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
337
338	scatterwalk_map_and_copy(rctx->datbuf.buf + rctx->residue.size,
339				 rctx->src_sg, 0, req->nbytes - nresidue, 0);
340
341	scatterwalk_map_and_copy(rctx->residue.buf, rctx->src_sg,
342				 req->nbytes - nresidue, nresidue, 0);
343
344	/* Update residue value with the residue after current block */
345	rctx->residue.size = nresidue;
346
347	rctx->config = tegra_sha_get_config(rctx->alg) |
348			SE_SHA_DST_HASH_REG;
349
350	/*
351	 * If this is not the first 'update' call, paste the previous copied
352	 * intermediate results to the registers so that it gets picked up.
353	 * This is to support the import/export functionality.
354	 */
355	if (!(rctx->task & SHA_FIRST))
356		tegra_sha_paste_hash_result(ctx->se, rctx);
357
358	size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
359
360	ret = tegra_se_host1x_submit(ctx->se, size);
361
362	/*
363	 * If this is not the final update, copy the intermediate results
364	 * from the registers so that it can be used in the next 'update'
365	 * call. This is to support the import/export functionality.
366	 */
367	if (!(rctx->task & SHA_FINAL))
368		tegra_sha_copy_hash_result(ctx->se, rctx);
369
370	return ret;
371}
372
373static int tegra_sha_do_final(struct ahash_request *req)
374{
375	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
376	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
377	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
378	struct tegra_se *se = ctx->se;
379	u32 *cpuvaddr = se->cmdbuf->addr;
380	int size, ret = 0;
381
382	memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
383	rctx->datbuf.size = rctx->residue.size;
384	rctx->total_len += rctx->residue.size;
385
386	rctx->config = tegra_sha_get_config(rctx->alg) |
387		       SE_SHA_DST_MEMORY;
388
389	size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
390
391	ret = tegra_se_host1x_submit(se, size);
392	if (ret)
393		goto out;
394
395	/* Copy result */
396	memcpy(req->result, rctx->digest.buf, rctx->digest.size);
397
398out:
399	dma_free_coherent(se->dev, SE_SHA_BUFLEN,
400			  rctx->datbuf.buf, rctx->datbuf.addr);
401	dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm),
402			  rctx->residue.buf, rctx->residue.addr);
403	dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
404			  rctx->digest.addr);
405	return ret;
406}
407
408static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
409{
410	struct ahash_request *req = ahash_request_cast(areq);
411	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
412	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
413	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
414	struct tegra_se *se = ctx->se;
415	int ret = 0;
416
417	if (rctx->task & SHA_UPDATE) {
418		ret = tegra_sha_do_update(req);
419		rctx->task &= ~SHA_UPDATE;
420	}
421
422	if (rctx->task & SHA_FINAL) {
423		ret = tegra_sha_do_final(req);
424		rctx->task &= ~SHA_FINAL;
425	}
426
427	crypto_finalize_hash_request(se->engine, req, ret);
428
429	return 0;
430}
431
432static void tegra_sha_init_fallback(struct crypto_ahash *tfm, struct tegra_sha_ctx *ctx,
433				    const char *algname)
434{
435	unsigned int statesize;
436
437	ctx->fallback_tfm = crypto_alloc_ahash(algname, 0, CRYPTO_ALG_ASYNC |
438						CRYPTO_ALG_NEED_FALLBACK);
439
440	if (IS_ERR(ctx->fallback_tfm)) {
441		dev_warn(ctx->se->dev,
442			 "failed to allocate fallback for %s\n", algname);
443		ctx->fallback_tfm = NULL;
444		return;
445	}
446
447	statesize = crypto_ahash_statesize(ctx->fallback_tfm);
448
449	if (statesize > sizeof(struct tegra_sha_reqctx))
450		crypto_ahash_set_statesize(tfm, statesize);
451
452	/* Update reqsize if fallback is added */
453	crypto_ahash_set_reqsize(tfm,
454				 sizeof(struct tegra_sha_reqctx) +
455			crypto_ahash_reqsize(ctx->fallback_tfm));
456}
457
458static int tegra_sha_cra_init(struct crypto_tfm *tfm)
459{
460	struct tegra_sha_ctx *ctx = crypto_tfm_ctx(tfm);
461	struct crypto_ahash *ahash_tfm = __crypto_ahash_cast(tfm);
462	struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg);
463	struct tegra_se_alg *se_alg;
464	const char *algname;
465	int ret;
466
467	algname = crypto_tfm_alg_name(tfm);
468	se_alg = container_of(alg, struct tegra_se_alg, alg.ahash.base);
469
470	crypto_ahash_set_reqsize(ahash_tfm, sizeof(struct tegra_sha_reqctx));
471
472	ctx->se = se_alg->se_dev;
473	ctx->fallback = false;
474	ctx->key_id = 0;
475
476	ret = se_algname_to_algid(algname);
477	if (ret < 0) {
478		dev_err(ctx->se->dev, "invalid algorithm\n");
479		return ret;
480	}
481
482	if (se_alg->alg_base)
483		tegra_sha_init_fallback(ahash_tfm, ctx, algname);
484
485	ctx->alg = ret;
486
487	return 0;
488}
489
490static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
491{
492	struct tegra_sha_ctx *ctx = crypto_tfm_ctx(tfm);
493
494	if (ctx->fallback_tfm)
495		crypto_free_ahash(ctx->fallback_tfm);
496
497	tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
498}
499
500static int tegra_sha_init(struct ahash_request *req)
501{
502	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
503	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
504	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
505	struct tegra_se *se = ctx->se;
506
507	if (ctx->fallback)
508		return tegra_sha_fallback_init(req);
509
510	rctx->total_len = 0;
511	rctx->datbuf.size = 0;
512	rctx->residue.size = 0;
513	rctx->key_id = ctx->key_id;
514	rctx->task = SHA_FIRST;
515	rctx->alg = ctx->alg;
516	rctx->blk_size = crypto_ahash_blocksize(tfm);
517	rctx->digest.size = crypto_ahash_digestsize(tfm);
518
519	rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
520					      &rctx->digest.addr, GFP_KERNEL);
521	if (!rctx->digest.buf)
522		goto digbuf_fail;
523
524	rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
525					       &rctx->residue.addr, GFP_KERNEL);
526	if (!rctx->residue.buf)
527		goto resbuf_fail;
528
529	rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
530					      &rctx->datbuf.addr, GFP_KERNEL);
531	if (!rctx->datbuf.buf)
532		goto datbuf_fail;
533
534	return 0;
535
536datbuf_fail:
537	dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
538			  rctx->residue.addr);
539resbuf_fail:
540	dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf,
541			  rctx->datbuf.addr);
542digbuf_fail:
543	return -ENOMEM;
544}
545
546static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
547				      unsigned int keylen)
548{
549	if (!ctx->fallback_tfm) {
550		dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
551		return -EINVAL;
552	}
553
554	ctx->fallback = true;
555	return crypto_ahash_setkey(ctx->fallback_tfm, key, keylen);
556}
557
558static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
559			     unsigned int keylen)
560{
561	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
562
563	if (aes_check_keylen(keylen))
564		return tegra_hmac_fallback_setkey(ctx, key, keylen);
565
566	ctx->fallback = false;
567
568	return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
569}
570
571static int tegra_sha_update(struct ahash_request *req)
572{
573	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
574	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
575	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
576
577	if (ctx->fallback)
578		return tegra_sha_fallback_update(req);
579
580	rctx->task |= SHA_UPDATE;
581
582	return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
583}
584
585static int tegra_sha_final(struct ahash_request *req)
586{
587	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
588	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
589	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
590
591	if (ctx->fallback)
592		return tegra_sha_fallback_final(req);
593
594	rctx->task |= SHA_FINAL;
595
596	return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
597}
598
599static int tegra_sha_finup(struct ahash_request *req)
600{
601	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
602	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
603	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
604
605	if (ctx->fallback)
606		return tegra_sha_fallback_finup(req);
607
608	rctx->task |= SHA_UPDATE | SHA_FINAL;
609
610	return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
611}
612
613static int tegra_sha_digest(struct ahash_request *req)
614{
615	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
616	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
617	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
618
619	if (ctx->fallback)
620		return tegra_sha_fallback_digest(req);
621
622	tegra_sha_init(req);
623	rctx->task |= SHA_UPDATE | SHA_FINAL;
624
625	return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
626}
627
628static int tegra_sha_export(struct ahash_request *req, void *out)
629{
630	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
631	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
632	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
633
634	if (ctx->fallback)
635		return tegra_sha_fallback_export(req, out);
636
637	memcpy(out, rctx, sizeof(*rctx));
638
639	return 0;
640}
641
642static int tegra_sha_import(struct ahash_request *req, const void *in)
643{
644	struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
645	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
646	struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
647
648	if (ctx->fallback)
649		return tegra_sha_fallback_import(req, in);
650
651	memcpy(rctx, in, sizeof(*rctx));
652
653	return 0;
654}
655
656static struct tegra_se_alg tegra_hash_algs[] = {
657	{
658		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
659		.alg.ahash.base = {
660			.init = tegra_sha_init,
661			.update = tegra_sha_update,
662			.final = tegra_sha_final,
663			.finup = tegra_sha_finup,
664			.digest = tegra_sha_digest,
665			.export = tegra_sha_export,
666			.import = tegra_sha_import,
667			.halg.digestsize = SHA1_DIGEST_SIZE,
668			.halg.statesize = sizeof(struct tegra_sha_reqctx),
669			.halg.base = {
670				.cra_name = "sha1",
671				.cra_driver_name = "tegra-se-sha1",
672				.cra_priority = 300,
673				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
674				.cra_blocksize = SHA1_BLOCK_SIZE,
675				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
676				.cra_alignmask = 0,
677				.cra_module = THIS_MODULE,
678				.cra_init = tegra_sha_cra_init,
679				.cra_exit = tegra_sha_cra_exit,
680			}
681		}
682	}, {
683		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
684		.alg.ahash.base = {
685			.init = tegra_sha_init,
686			.update = tegra_sha_update,
687			.final = tegra_sha_final,
688			.finup = tegra_sha_finup,
689			.digest = tegra_sha_digest,
690			.export = tegra_sha_export,
691			.import = tegra_sha_import,
692			.halg.digestsize = SHA224_DIGEST_SIZE,
693			.halg.statesize = sizeof(struct tegra_sha_reqctx),
694			.halg.base = {
695				.cra_name = "sha224",
696				.cra_driver_name = "tegra-se-sha224",
697				.cra_priority = 300,
698				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
699				.cra_blocksize = SHA224_BLOCK_SIZE,
700				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
701				.cra_alignmask = 0,
702				.cra_module = THIS_MODULE,
703				.cra_init = tegra_sha_cra_init,
704				.cra_exit = tegra_sha_cra_exit,
705			}
706		}
707	}, {
708		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
709		.alg.ahash.base = {
710			.init = tegra_sha_init,
711			.update = tegra_sha_update,
712			.final = tegra_sha_final,
713			.finup = tegra_sha_finup,
714			.digest = tegra_sha_digest,
715			.export = tegra_sha_export,
716			.import = tegra_sha_import,
717			.halg.digestsize = SHA256_DIGEST_SIZE,
718			.halg.statesize = sizeof(struct tegra_sha_reqctx),
719			.halg.base = {
720				.cra_name = "sha256",
721				.cra_driver_name = "tegra-se-sha256",
722				.cra_priority = 300,
723				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
724				.cra_blocksize = SHA256_BLOCK_SIZE,
725				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
726				.cra_alignmask = 0,
727				.cra_module = THIS_MODULE,
728				.cra_init = tegra_sha_cra_init,
729				.cra_exit = tegra_sha_cra_exit,
730			}
731		}
732	}, {
733		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
734		.alg.ahash.base = {
735			.init = tegra_sha_init,
736			.update = tegra_sha_update,
737			.final = tegra_sha_final,
738			.finup = tegra_sha_finup,
739			.digest = tegra_sha_digest,
740			.export = tegra_sha_export,
741			.import = tegra_sha_import,
742			.halg.digestsize = SHA384_DIGEST_SIZE,
743			.halg.statesize = sizeof(struct tegra_sha_reqctx),
744			.halg.base = {
745				.cra_name = "sha384",
746				.cra_driver_name = "tegra-se-sha384",
747				.cra_priority = 300,
748				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
749				.cra_blocksize = SHA384_BLOCK_SIZE,
750				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
751				.cra_alignmask = 0,
752				.cra_module = THIS_MODULE,
753				.cra_init = tegra_sha_cra_init,
754				.cra_exit = tegra_sha_cra_exit,
755			}
756		}
757	}, {
758		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
759		.alg.ahash.base = {
760			.init = tegra_sha_init,
761			.update = tegra_sha_update,
762			.final = tegra_sha_final,
763			.finup = tegra_sha_finup,
764			.digest = tegra_sha_digest,
765			.export = tegra_sha_export,
766			.import = tegra_sha_import,
767			.halg.digestsize = SHA512_DIGEST_SIZE,
768			.halg.statesize = sizeof(struct tegra_sha_reqctx),
769			.halg.base = {
770				.cra_name = "sha512",
771				.cra_driver_name = "tegra-se-sha512",
772				.cra_priority = 300,
773				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
774				.cra_blocksize = SHA512_BLOCK_SIZE,
775				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
776				.cra_alignmask = 0,
777				.cra_module = THIS_MODULE,
778				.cra_init = tegra_sha_cra_init,
779				.cra_exit = tegra_sha_cra_exit,
780			}
781		}
782	}, {
783		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
784		.alg.ahash.base = {
785			.init = tegra_sha_init,
786			.update = tegra_sha_update,
787			.final = tegra_sha_final,
788			.finup = tegra_sha_finup,
789			.digest = tegra_sha_digest,
790			.export = tegra_sha_export,
791			.import = tegra_sha_import,
792			.halg.digestsize = SHA3_224_DIGEST_SIZE,
793			.halg.statesize = sizeof(struct tegra_sha_reqctx),
794			.halg.base = {
795				.cra_name = "sha3-224",
796				.cra_driver_name = "tegra-se-sha3-224",
797				.cra_priority = 300,
798				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
799				.cra_blocksize = SHA3_224_BLOCK_SIZE,
800				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
801				.cra_alignmask = 0,
802				.cra_module = THIS_MODULE,
803				.cra_init = tegra_sha_cra_init,
804				.cra_exit = tegra_sha_cra_exit,
805			}
806		}
807	}, {
808		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
809		.alg.ahash.base = {
810			.init = tegra_sha_init,
811			.update = tegra_sha_update,
812			.final = tegra_sha_final,
813			.finup = tegra_sha_finup,
814			.digest = tegra_sha_digest,
815			.export = tegra_sha_export,
816			.import = tegra_sha_import,
817			.halg.digestsize = SHA3_256_DIGEST_SIZE,
818			.halg.statesize = sizeof(struct tegra_sha_reqctx),
819			.halg.base = {
820				.cra_name = "sha3-256",
821				.cra_driver_name = "tegra-se-sha3-256",
822				.cra_priority = 300,
823				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
824				.cra_blocksize = SHA3_256_BLOCK_SIZE,
825				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
826				.cra_alignmask = 0,
827				.cra_module = THIS_MODULE,
828				.cra_init = tegra_sha_cra_init,
829				.cra_exit = tegra_sha_cra_exit,
830			}
831		}
832	}, {
833		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
834		.alg.ahash.base = {
835			.init = tegra_sha_init,
836			.update = tegra_sha_update,
837			.final = tegra_sha_final,
838			.finup = tegra_sha_finup,
839			.digest = tegra_sha_digest,
840			.export = tegra_sha_export,
841			.import = tegra_sha_import,
842			.halg.digestsize = SHA3_384_DIGEST_SIZE,
843			.halg.statesize = sizeof(struct tegra_sha_reqctx),
844			.halg.base = {
845				.cra_name = "sha3-384",
846				.cra_driver_name = "tegra-se-sha3-384",
847				.cra_priority = 300,
848				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
849				.cra_blocksize = SHA3_384_BLOCK_SIZE,
850				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
851				.cra_alignmask = 0,
852				.cra_module = THIS_MODULE,
853				.cra_init = tegra_sha_cra_init,
854				.cra_exit = tegra_sha_cra_exit,
855			}
856		}
857	}, {
858		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
859		.alg.ahash.base = {
860			.init = tegra_sha_init,
861			.update = tegra_sha_update,
862			.final = tegra_sha_final,
863			.finup = tegra_sha_finup,
864			.digest = tegra_sha_digest,
865			.export = tegra_sha_export,
866			.import = tegra_sha_import,
867			.halg.digestsize = SHA3_512_DIGEST_SIZE,
868			.halg.statesize = sizeof(struct tegra_sha_reqctx),
869			.halg.base = {
870				.cra_name = "sha3-512",
871				.cra_driver_name = "tegra-se-sha3-512",
872				.cra_priority = 300,
873				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
874				.cra_blocksize = SHA3_512_BLOCK_SIZE,
875				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
876				.cra_alignmask = 0,
877				.cra_module = THIS_MODULE,
878				.cra_init = tegra_sha_cra_init,
879				.cra_exit = tegra_sha_cra_exit,
880			}
881		}
882	}, {
883		.alg_base = "sha224",
884		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
885		.alg.ahash.base = {
886			.init = tegra_sha_init,
887			.update = tegra_sha_update,
888			.final = tegra_sha_final,
889			.finup = tegra_sha_finup,
890			.digest = tegra_sha_digest,
891			.export = tegra_sha_export,
892			.import = tegra_sha_import,
893			.setkey = tegra_hmac_setkey,
894			.halg.digestsize = SHA224_DIGEST_SIZE,
895			.halg.statesize = sizeof(struct tegra_sha_reqctx),
896			.halg.base = {
897				.cra_name = "hmac(sha224)",
898				.cra_driver_name = "tegra-se-hmac-sha224",
899				.cra_priority = 300,
900				.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
901				.cra_blocksize = SHA224_BLOCK_SIZE,
902				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
903				.cra_alignmask = 0,
904				.cra_module = THIS_MODULE,
905				.cra_init = tegra_sha_cra_init,
906				.cra_exit = tegra_sha_cra_exit,
907			}
908		}
909	}, {
910		.alg_base = "sha256",
911		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
912		.alg.ahash.base = {
913			.init = tegra_sha_init,
914			.update = tegra_sha_update,
915			.final = tegra_sha_final,
916			.finup = tegra_sha_finup,
917			.digest = tegra_sha_digest,
918			.export = tegra_sha_export,
919			.import = tegra_sha_import,
920			.setkey = tegra_hmac_setkey,
921			.halg.digestsize = SHA256_DIGEST_SIZE,
922			.halg.statesize = sizeof(struct tegra_sha_reqctx),
923			.halg.base = {
924				.cra_name = "hmac(sha256)",
925				.cra_driver_name = "tegra-se-hmac-sha256",
926				.cra_priority = 300,
927				.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
928				.cra_blocksize = SHA256_BLOCK_SIZE,
929				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
930				.cra_alignmask = 0,
931				.cra_module = THIS_MODULE,
932				.cra_init = tegra_sha_cra_init,
933				.cra_exit = tegra_sha_cra_exit,
934			}
935		}
936	}, {
937		.alg_base = "sha384",
938		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
939		.alg.ahash.base = {
940			.init = tegra_sha_init,
941			.update = tegra_sha_update,
942			.final = tegra_sha_final,
943			.finup = tegra_sha_finup,
944			.digest = tegra_sha_digest,
945			.export = tegra_sha_export,
946			.import = tegra_sha_import,
947			.setkey = tegra_hmac_setkey,
948			.halg.digestsize = SHA384_DIGEST_SIZE,
949			.halg.statesize = sizeof(struct tegra_sha_reqctx),
950			.halg.base = {
951				.cra_name = "hmac(sha384)",
952				.cra_driver_name = "tegra-se-hmac-sha384",
953				.cra_priority = 300,
954				.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
955				.cra_blocksize = SHA384_BLOCK_SIZE,
956				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
957				.cra_alignmask = 0,
958				.cra_module = THIS_MODULE,
959				.cra_init = tegra_sha_cra_init,
960				.cra_exit = tegra_sha_cra_exit,
961			}
962		}
963	}, {
964		.alg_base = "sha512",
965		.alg.ahash.op.do_one_request = tegra_sha_do_one_req,
966		.alg.ahash.base = {
967			.init = tegra_sha_init,
968			.update = tegra_sha_update,
969			.final = tegra_sha_final,
970			.finup = tegra_sha_finup,
971			.digest = tegra_sha_digest,
972			.export = tegra_sha_export,
973			.import = tegra_sha_import,
974			.setkey = tegra_hmac_setkey,
975			.halg.digestsize = SHA512_DIGEST_SIZE,
976			.halg.statesize = sizeof(struct tegra_sha_reqctx),
977			.halg.base = {
978				.cra_name = "hmac(sha512)",
979				.cra_driver_name = "tegra-se-hmac-sha512",
980				.cra_priority = 300,
981				.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
982				.cra_blocksize = SHA512_BLOCK_SIZE,
983				.cra_ctxsize = sizeof(struct tegra_sha_ctx),
984				.cra_alignmask = 0,
985				.cra_module = THIS_MODULE,
986				.cra_init = tegra_sha_cra_init,
987				.cra_exit = tegra_sha_cra_exit,
988			}
989		}
990	}
991};
992
993static int tegra_hash_kac_manifest(u32 user, u32 alg, u32 keylen)
994{
995	int manifest;
996
997	manifest = SE_KAC_USER_NS;
998
999	switch (alg) {
1000	case SE_ALG_HMAC_SHA224:
1001	case SE_ALG_HMAC_SHA256:
1002	case SE_ALG_HMAC_SHA384:
1003	case SE_ALG_HMAC_SHA512:
1004		manifest |= SE_KAC_HMAC;
1005		break;
1006	default:
1007		return -EINVAL;
1008	}
1009
1010	switch (keylen) {
1011	case AES_KEYSIZE_128:
1012		manifest |= SE_KAC_SIZE_128;
1013		break;
1014	case AES_KEYSIZE_192:
1015		manifest |= SE_KAC_SIZE_192;
1016		break;
1017	case AES_KEYSIZE_256:
1018	default:
1019		manifest |= SE_KAC_SIZE_256;
1020		break;
1021	}
1022
1023	return manifest;
1024}
1025
1026int tegra_init_hash(struct tegra_se *se)
1027{
1028	struct ahash_engine_alg *alg;
1029	int i, ret;
1030
1031	se->manifest = tegra_hash_kac_manifest;
1032
1033	for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++) {
1034		tegra_hash_algs[i].se_dev = se;
1035		alg = &tegra_hash_algs[i].alg.ahash;
1036
1037		ret = crypto_engine_register_ahash(alg);
1038		if (ret) {
1039			dev_err(se->dev, "failed to register %s\n",
1040				alg->base.halg.base.cra_name);
1041			goto sha_err;
1042		}
1043	}
1044
1045	return 0;
1046
1047sha_err:
1048	while (i--)
1049		crypto_engine_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
1050
1051	return ret;
1052}
1053
1054void tegra_deinit_hash(struct tegra_se *se)
1055{
1056	int i;
1057
1058	for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++)
1059		crypto_engine_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
1060}
1061