brintos

brintos / linux-shallow public Read only

0
0
Text · 29.0 KiB · 4d4bd72 Raw
1061 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2// 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 the227	 * 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 and324	 * 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 copied352	 * 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 results364	 * 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